Skip to content

Commit ce6801f

Browse files
Auto merge of #147237 - yotamofek:pr/rustdoc/highlight/optimize-end_expansion, r=<try>
[rustdoc] Optimize "highlight::end_expansion"
2 parents d4ae855 + fd23589 commit ce6801f

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

src/librustdoc/html/highlight.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use std::borrow::Cow;
99
use std::collections::VecDeque;
1010
use std::fmt::{self, Display, Write};
11-
use std::iter;
11+
use std::{cmp, iter};
1212

1313
use rustc_data_structures::fx::FxIndexMap;
1414
use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};
@@ -345,33 +345,39 @@ fn end_expansion<'a, W: Write>(
345345
token_handler.pending_elems.push((Cow::Borrowed("</span>"), Some(Class::Expansion)));
346346
return Some(expanded_code);
347347
}
348+
349+
const CLOSE_EXPANSION: &str = "</span></span>";
350+
348351
if expansion_start_tags.is_empty() && token_handler.closing_tags.is_empty() {
349352
// No need tag opened so we can just close expansion.
350-
token_handler.pending_elems.push((Cow::Borrowed("</span></span>"), Some(Class::Expansion)));
353+
token_handler.pending_elems.push((Cow::Borrowed(CLOSE_EXPANSION), Some(Class::Expansion)));
351354
return None;
352355
}
353356

354-
// If tags were opened inside the expansion, we need to close them and re-open them outside
355-
// of the expansion span.
356-
let mut out = String::new();
357-
let mut end = String::new();
357+
let skip = iter::zip(token_handler.closing_tags.as_slice(), expansion_start_tags)
358+
.position(|(tag, start_tag)| tag != start_tag)
359+
.unwrap_or_else(|| cmp::min(token_handler.closing_tags.len(), expansion_start_tags.len()));
358360

359-
let mut closing_tags = token_handler.closing_tags.iter().peekable();
360-
let mut start_closing_tags = expansion_start_tags.iter().peekable();
361+
let tags = iter::chain(
362+
expansion_start_tags.iter().skip(skip),
363+
token_handler.closing_tags.iter().skip(skip),
364+
);
361365

362-
while let (Some(tag), Some(start_tag)) = (closing_tags.peek(), start_closing_tags.peek())
363-
&& tag == start_tag
364-
{
365-
closing_tags.next();
366-
start_closing_tags.next();
366+
let len = tags
367+
.clone()
368+
.map(|(tag, class)| tag.len() + "<span class=\"\">".len() + class.as_html().len())
369+
.sum::<usize>();
370+
let mut elem = String::with_capacity(len + CLOSE_EXPANSION.len());
371+
elem.push_str(CLOSE_EXPANSION);
372+
373+
for (tag, _) in tags.clone() {
374+
elem.push_str(tag);
367375
}
368-
for (tag, class) in start_closing_tags.chain(closing_tags) {
369-
out.push_str(tag);
370-
end.push_str(&format!("<span class=\"{}\">", class.as_html()));
376+
for (_, class) in tags {
377+
write!(elem, "<span class=\"{}\">", class.as_html()).unwrap();
371378
}
372-
token_handler
373-
.pending_elems
374-
.push((Cow::Owned(format!("</span></span>{out}{end}")), Some(Class::Expansion)));
379+
380+
token_handler.pending_elems.push((Cow::Owned(elem), Some(Class::Expansion)));
375381
None
376382
}
377383

0 commit comments

Comments
 (0)