Skip to content

Commit ee53c6e

Browse files
Auto merge of #147106 - yotamofek:pr/rustdoc/highlight-optimizations, r=<try>
Small `highlight.rs` optimizations
2 parents c0ee51f + 89d1e98 commit ee53c6e

File tree

1 file changed

+76
-42
lines changed

1 file changed

+76
-42
lines changed

src/librustdoc/html/highlight.rs

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::collections::VecDeque;
1010
use std::fmt::{self, Display, Write};
1111
use std::iter;
1212

13+
use arrayvec::ArrayVec;
1314
use rustc_data_structures::fx::FxIndexMap;
1415
use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
1516
use rustc_span::edition::Edition;
@@ -818,7 +819,7 @@ impl<'src> Classifier<'src> {
818819
}
819820

820821
/// Concatenate colons and idents as one when possible.
821-
fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> {
822+
fn get_full_ident_path(&mut self) -> ArrayVec<(TokenKind, usize, usize), 2> {
822823
let start = self.byte_pos as usize;
823824
let mut pos = start;
824825
let mut has_ident = false;
@@ -832,13 +833,16 @@ impl<'src> Classifier<'src> {
832833
// Ident path can start with "::" but if we already have content in the ident path,
833834
// the "::" is mandatory.
834835
if has_ident && nb == 0 {
835-
return vec![(TokenKind::Ident, start, pos)];
836+
return ArrayVec::from_iter([(TokenKind::Ident, start, pos)]);
836837
} else if nb != 0 && nb != 2 {
837-
if has_ident {
838-
return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)];
838+
return if has_ident {
839+
ArrayVec::from_iter([
840+
(TokenKind::Ident, start, pos),
841+
(TokenKind::Colon, pos, pos + nb),
842+
])
839843
} else {
840-
return vec![(TokenKind::Colon, start, pos + nb)];
841-
}
844+
ArrayVec::from_iter([(TokenKind::Colon, start, pos + nb)])
845+
};
842846
}
843847

844848
if let Some((None, text)) = self.tokens.peek().map(|(token, text)| {
@@ -854,15 +858,21 @@ impl<'src> Classifier<'src> {
854858
pos += text.len() + nb;
855859
has_ident = true;
856860
self.tokens.next();
857-
} else if nb > 0 && has_ident {
858-
return vec![(TokenKind::Ident, start, pos), (TokenKind::Colon, pos, pos + nb)];
861+
continue;
862+
}
863+
864+
return if nb > 0 && has_ident {
865+
ArrayVec::from_iter([
866+
(TokenKind::Ident, start, pos),
867+
(TokenKind::Colon, pos, pos + nb),
868+
])
859869
} else if nb > 0 {
860-
return vec![(TokenKind::Colon, start, start + nb)];
870+
ArrayVec::from_iter([(TokenKind::Colon, start, start + nb)])
861871
} else if has_ident {
862-
return vec![(TokenKind::Ident, start, pos)];
872+
ArrayVec::from_iter([(TokenKind::Ident, start, pos)])
863873
} else {
864-
return Vec::new();
865-
}
874+
ArrayVec::new()
875+
};
866876
}
867877
}
868878

@@ -885,7 +895,7 @@ impl<'src> Classifier<'src> {
885895
/// The general structure for this method is to iterate over each token,
886896
/// possibly giving it an HTML span with a class specifying what flavor of
887897
/// token is used.
888-
fn highlight(mut self, sink: &mut dyn FnMut(Span, Highlight<'src>)) {
898+
fn highlight(mut self, mut sink: impl FnMut(Span, Highlight<'src>)) {
889899
loop {
890900
if let Some(decs) = self.decorations.as_mut() {
891901
let byte_pos = self.byte_pos;
@@ -903,21 +913,20 @@ impl<'src> Classifier<'src> {
903913
if self
904914
.tokens
905915
.peek()
906-
.map(|t| matches!(t.0, TokenKind::Colon | TokenKind::Ident))
907-
.unwrap_or(false)
916+
.is_some_and(|(kind, _)| matches!(kind, TokenKind::Colon | TokenKind::Ident))
908917
{
909918
let tokens = self.get_full_ident_path();
910919
for (token, start, end) in &tokens {
911920
let text = &self.src[*start..*end];
912-
self.advance(*token, text, sink, *start as u32);
921+
self.advance(*token, text, &mut sink, *start as u32);
913922
self.byte_pos += text.len() as u32;
914923
}
915924
if !tokens.is_empty() {
916925
continue;
917926
}
918927
}
919928
if let Some((token, text, before)) = self.next() {
920-
self.advance(token, text, sink, before);
929+
self.advance(token, text, &mut sink, before);
921930
} else {
922931
break;
923932
}
@@ -934,26 +943,28 @@ impl<'src> Classifier<'src> {
934943
&mut self,
935944
token: TokenKind,
936945
text: &'src str,
937-
sink: &mut dyn FnMut(Span, Highlight<'src>),
946+
mut sink: impl FnMut(Span, Highlight<'src>),
938947
before: u32,
939948
) {
940949
let lookahead = self.peek();
941950
let file_span = self.file_span;
942-
let no_highlight = |sink: &mut dyn FnMut(_, _)| {
943-
sink(new_span(before, text, file_span), Highlight::Token { text, class: None })
944-
};
945-
let whitespace = |sink: &mut dyn FnMut(_, _)| {
951+
let no_highlight =
952+
|| (new_span(before, text, file_span), Highlight::Token { text, class: None });
953+
let mut whitespace = |class| {
946954
let mut start = 0u32;
947955
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
948956
sink(
949957
new_span(before + start, part, file_span),
950-
Highlight::Token { text: part, class: None },
958+
Highlight::Token { text: part, class },
951959
);
952960
start += part.len() as u32;
953961
}
954962
};
955963
let class = match token {
956-
TokenKind::Whitespace => return whitespace(sink),
964+
TokenKind::Whitespace => {
965+
whitespace(None);
966+
return;
967+
}
957968
TokenKind::LineComment { doc_style } | TokenKind::BlockComment { doc_style, .. } => {
958969
if doc_style.is_some() {
959970
Class::DocComment
@@ -974,7 +985,10 @@ impl<'src> Classifier<'src> {
974985
// or a reference or pointer type. Unless, of course, it looks like
975986
// a logical and or a multiplication operator: `&&` or `* `.
976987
TokenKind::Star => match self.tokens.peek() {
977-
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
988+
Some((TokenKind::Whitespace, _)) => {
989+
whitespace(None);
990+
return;
991+
}
978992
Some((TokenKind::Ident, "mut")) => {
979993
self.next();
980994
sink(
@@ -1004,7 +1018,10 @@ impl<'src> Classifier<'src> {
10041018
sink(DUMMY_SP, Highlight::Token { text: "&=", class: None });
10051019
return;
10061020
}
1007-
Some((TokenKind::Whitespace, _)) => return whitespace(sink),
1021+
Some((TokenKind::Whitespace, _)) => {
1022+
whitespace(None);
1023+
return;
1024+
}
10081025
Some((TokenKind::Ident, "mut")) => {
10091026
self.next();
10101027
sink(
@@ -1028,7 +1045,11 @@ impl<'src> Classifier<'src> {
10281045
sink(DUMMY_SP, Highlight::Token { text: "=>", class: None });
10291046
return;
10301047
}
1031-
_ => return no_highlight(sink),
1048+
_ => {
1049+
let (span, highlight) = no_highlight();
1050+
sink(span, highlight);
1051+
return;
1052+
}
10321053
},
10331054
TokenKind::Minus if lookahead == Some(TokenKind::Gt) => {
10341055
self.next();
@@ -1045,7 +1066,11 @@ impl<'src> Classifier<'src> {
10451066
| TokenKind::Percent
10461067
| TokenKind::Bang
10471068
| TokenKind::Lt
1048-
| TokenKind::Gt => return no_highlight(sink),
1069+
| TokenKind::Gt => {
1070+
let (span, highlight) = no_highlight();
1071+
sink(span, highlight);
1072+
return;
1073+
}
10491074

10501075
// Miscellaneous, no highlighting.
10511076
TokenKind::Dot
@@ -1060,7 +1085,11 @@ impl<'src> Classifier<'src> {
10601085
| TokenKind::Tilde
10611086
| TokenKind::Colon
10621087
| TokenKind::Frontmatter { .. }
1063-
| TokenKind::Unknown => return no_highlight(sink),
1088+
| TokenKind::Unknown => {
1089+
let (span, highlight) = no_highlight();
1090+
sink(span, highlight);
1091+
return;
1092+
}
10641093

10651094
TokenKind::Question => Class::QuestionMark,
10661095

@@ -1069,7 +1098,11 @@ impl<'src> Classifier<'src> {
10691098
self.in_macro_nonterminal = true;
10701099
Class::MacroNonTerminal
10711100
}
1072-
_ => return no_highlight(sink),
1101+
_ => {
1102+
let (span, highlight) = no_highlight();
1103+
sink(span, highlight);
1104+
return;
1105+
}
10731106
},
10741107

10751108
// This might be the start of an attribute. We're going to want to
@@ -1100,9 +1133,11 @@ impl<'src> Classifier<'src> {
11001133
Highlight::EnterSpan { class: Class::Attribute },
11011134
);
11021135
}
1103-
_ => (),
1136+
_ => {}
11041137
}
1105-
return no_highlight(sink);
1138+
let (span, highlight) = no_highlight();
1139+
sink(span, highlight);
1140+
return;
11061141
}
11071142
TokenKind::CloseBracket => {
11081143
if self.in_attribute {
@@ -1114,7 +1149,9 @@ impl<'src> Classifier<'src> {
11141149
sink(DUMMY_SP, Highlight::ExitSpan);
11151150
return;
11161151
}
1117-
return no_highlight(sink);
1152+
let (span, highlight) = no_highlight();
1153+
sink(span, highlight);
1154+
return;
11181155
}
11191156
TokenKind::Literal { kind, .. } => match kind {
11201157
// Text literals.
@@ -1129,7 +1166,11 @@ impl<'src> Classifier<'src> {
11291166
// Number literals.
11301167
LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,
11311168
},
1132-
TokenKind::GuardedStrPrefix => return no_highlight(sink),
1169+
TokenKind::GuardedStrPrefix => {
1170+
let (span, highlight) = no_highlight();
1171+
sink(span, highlight);
1172+
return;
1173+
}
11331174
TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => {
11341175
self.in_macro = true;
11351176
let span = new_span(before, text, file_span);
@@ -1165,14 +1206,7 @@ impl<'src> Classifier<'src> {
11651206
};
11661207
// Anything that didn't return above is the simple case where we the
11671208
// class just spans a single token, so we can use the `string` method.
1168-
let mut start = 0u32;
1169-
for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
1170-
sink(
1171-
new_span(before + start, part, file_span),
1172-
Highlight::Token { text: part, class: Some(class) },
1173-
);
1174-
start += part.len() as u32;
1175-
}
1209+
whitespace(Some(class));
11761210
}
11771211

11781212
fn peek(&mut self) -> Option<TokenKind> {

0 commit comments

Comments
 (0)