Skip to content

Commit 48cbce8

Browse files
committed
rustdoc: Refactor keyword highlighting and make metavars take precedence
1 parent 130dc8f commit 48cbce8

File tree

1 file changed

+36
-46
lines changed

1 file changed

+36
-46
lines changed

src/librustdoc/html/highlight.rs

Lines changed: 36 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -754,22 +754,6 @@ impl<'a> Iterator for TokenIter<'a> {
754754
}
755755
}
756756

757-
/// Classifies into identifier class; returns `None` if this is a non-keyword identifier.
758-
fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> {
759-
let ignore: &[&str] =
760-
if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
761-
if ignore.contains(&text) {
762-
return None;
763-
}
764-
Some(match text {
765-
"ref" | "mut" => Class::RefKeyWord,
766-
"false" | "true" => Class::Bool,
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,
769-
_ => return None,
770-
})
771-
}
772-
773757
/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
774758
/// just the next item by using `peek_next`. The `peek` method always returns the next item after
775759
/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -787,16 +771,16 @@ impl<'a> PeekIter<'a> {
787771
Self { stored: VecDeque::new(), peek_pos: 0, iter }
788772
}
789773
/// Returns the next item after the current one. It doesn't interfere with `peek_next` output.
790-
fn peek(&mut self) -> Option<&(TokenKind, &'a str)> {
774+
fn peek(&mut self) -> Option<(TokenKind, &'a str)> {
791775
if self.stored.is_empty()
792776
&& let Some(next) = self.iter.next()
793777
{
794778
self.stored.push_back(next);
795779
}
796-
self.stored.front()
780+
self.stored.front().copied()
797781
}
798782
/// Returns the next item after the last one peeked. It doesn't interfere with `peek` output.
799-
fn peek_next(&mut self) -> Option<&(TokenKind, &'a str)> {
783+
fn peek_next(&mut self) -> Option<(TokenKind, &'a str)> {
800784
self.peek_pos += 1;
801785
if self.peek_pos - 1 < self.stored.len() {
802786
self.stored.get(self.peek_pos - 1)
@@ -806,6 +790,7 @@ impl<'a> PeekIter<'a> {
806790
} else {
807791
None
808792
}
793+
.copied()
809794
}
810795

811796
fn stop_peeking(&mut self) {
@@ -952,15 +937,9 @@ impl<'src> Classifier<'src> {
952937
}
953938
}
954939

955-
if let Some((None, text)) = self.tokens.peek().map(|(token, text)| {
956-
if *token == TokenKind::Ident {
957-
let class = get_real_ident_class(text, true);
958-
(class, text)
959-
} else {
960-
// Doesn't matter which Class we put in here...
961-
(Some(Class::Comment), text)
962-
}
963-
}) {
940+
if let Some((TokenKind::Ident, text)) = self.tokens.peek()
941+
&& !ident_is_keyword(text)
942+
{
964943
// We only "add" the colon if there is an ident behind.
965944
pos += text.len() + nb;
966945
has_ident = true;
@@ -1206,22 +1185,7 @@ impl<'src> Classifier<'src> {
12061185
sink(span, Highlight::Token { text, class: None });
12071186
return;
12081187
}
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-
},
1188+
TokenKind::Ident => self.classify_ident(before, text),
12251189
TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
12261190
Class::Ident(new_span(before, text, file_span))
12271191
}
@@ -1242,6 +1206,27 @@ impl<'src> Classifier<'src> {
12421206
}
12431207
}
12441208

1209+
fn classify_ident(&mut self, before: u32, text: &'src str) -> Class {
1210+
// Macro non-terminals (meta vars) take precedence.
1211+
if self.in_macro_nonterminal {
1212+
self.in_macro_nonterminal = false;
1213+
return Class::MacroNonTerminal;
1214+
}
1215+
1216+
let file_span = self.file_span;
1217+
let span = || new_span(before, text, file_span);
1218+
1219+
match text {
1220+
"ref" | "mut" => Class::RefKeyWord,
1221+
"false" | "true" => Class::Bool,
1222+
"self" | "Self" => Class::Self_(span()),
1223+
"Option" | "Result" => Class::PreludeTy(span()),
1224+
"Some" | "None" | "Ok" | "Err" => Class::PreludeVal(span()),
1225+
_ if ident_is_keyword(text) || self.ident_is_weak_keyword(text) => Class::KeyWord,
1226+
_ => Class::Ident(span()),
1227+
}
1228+
}
1229+
12451230
fn ident_is_weak_keyword(&mut self, text: &str) -> bool {
12461231
let matches = match text {
12471232
"auto" => |text| text == "trait", // `auto trait Trait {}` (`auto_traits`)
@@ -1255,11 +1240,11 @@ impl<'src> Classifier<'src> {
12551240
}
12561241

12571242
fn peek(&mut self) -> Option<TokenKind> {
1258-
self.tokens.peek().map(|&(kind, _)| kind)
1243+
self.tokens.peek().map(|(kind, _)| kind)
12591244
}
12601245

12611246
fn peek_non_trivia(&mut self) -> Option<(TokenKind, &str)> {
1262-
while let Some(&token @ (kind, _)) = self.tokens.peek_next() {
1247+
while let Some(token @ (kind, _)) = self.tokens.peek_next() {
12631248
if let TokenKind::Whitespace
12641249
| TokenKind::LineComment { doc_style: None }
12651250
| TokenKind::BlockComment { doc_style: None, .. } = kind
@@ -1274,6 +1259,11 @@ impl<'src> Classifier<'src> {
12741259
}
12751260
}
12761261

1262+
fn ident_is_keyword(text: &str) -> bool {
1263+
// FIXME(#148221): Don't hard-code the edition. The classifier should take it as an argument.
1264+
Symbol::intern(text).is_reserved(|| Edition::Edition2024)
1265+
}
1266+
12771267
fn generate_link_to_def(
12781268
out: &mut impl Write,
12791269
text_s: &str,

0 commit comments

Comments
 (0)