Auto merge of #147106 - yotamofek:pr/rustdoc/highlight-optimizations,… · rust-lang/rust@ee53c6e (original) (raw)

`@@ -10,6 +10,7 @@ use std::collections::VecDeque;

`

10

10

`use std::fmt::{self, Display, Write};

`

11

11

`use std::iter;

`

12

12

``

``

13

`+

use arrayvec::ArrayVec;

`

13

14

`use rustc_data_structures::fx::FxIndexMap;

`

14

15

`use rustc_lexer::{Cursor, FrontmatterAllowed, LiteralKind, TokenKind};

`

15

16

`use rustc_span::edition::Edition;

`

`@@ -818,7 +819,7 @@ impl<'src> Classifier<'src> {

`

818

819

`}

`

819

820

``

820

821

`/// 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> {

`

822

823

`let start = self.byte_pos as usize;

`

823

824

`let mut pos = start;

`

824

825

`let mut has_ident = false;

`

`@@ -832,13 +833,16 @@ impl<'src> Classifier<'src> {

`

832

833

`// Ident path can start with "::" but if we already have content in the ident path,

`

833

834

`// the "::" is mandatory.

`

834

835

`if has_ident && nb == 0 {

`

835

``

`-

return vec![(TokenKind::Ident, start, pos)];

`

``

836

`+

return ArrayVec::from_iter([(TokenKind::Ident, start, pos)]);

`

836

837

`} 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

`+

])

`

839

843

`} else {

`

840

``

`-

return vec![(TokenKind::Colon, start, pos + nb)];

`

841

``

`-

}

`

``

844

`+

ArrayVec::from_iter([(TokenKind::Colon, start, pos + nb)])

`

``

845

`+

};

`

842

846

`}

`

843

847

``

844

848

`if let Some((None, text)) = self.tokens.peek().map(|(token, text)| {

`

`@@ -854,15 +858,21 @@ impl<'src> Classifier<'src> {

`

854

858

` pos += text.len() + nb;

`

855

859

` has_ident = true;

`

856

860

`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

`+

])

`

859

869

`} else if nb > 0 {

`

860

``

`-

return vec![(TokenKind::Colon, start, start + nb)];

`

``

870

`+

ArrayVec::from_iter([(TokenKind::Colon, start, start + nb)])

`

861

871

`} else if has_ident {

`

862

``

`-

return vec![(TokenKind::Ident, start, pos)];

`

``

872

`+

ArrayVec::from_iter([(TokenKind::Ident, start, pos)])

`

863

873

`} else {

`

864

``

`-

return Vec::new();

`

865

``

`-

}

`

``

874

`+

ArrayVec::new()

`

``

875

`+

};

`

866

876

`}

`

867

877

`}

`

868

878

``

`@@ -885,7 +895,7 @@ impl<'src> Classifier<'src> {

`

885

895

`/// The general structure for this method is to iterate over each token,

`

886

896

`/// possibly giving it an HTML span with a class specifying what flavor of

`

887

897

`/// 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>)) {

`

889

899

`loop {

`

890

900

`if let Some(decs) = self.decorations.as_mut() {

`

891

901

`let byte_pos = self.byte_pos;

`

`@@ -903,21 +913,20 @@ impl<'src> Classifier<'src> {

`

903

913

`if self

`

904

914

`.tokens

`

905

915

`.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))

`

908

917

`{

`

909

918

`let tokens = self.get_full_ident_path();

`

910

919

`for (token, start, end) in &tokens {

`

911

920

`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);

`

913

922

`self.byte_pos += text.len() as u32;

`

914

923

`}

`

915

924

`if !tokens.is_empty() {

`

916

925

`continue;

`

917

926

`}

`

918

927

`}

`

919

928

`if let Some((token, text, before)) = self.next() {

`

920

``

`-

self.advance(token, text, sink, before);

`

``

929

`+

self.advance(token, text, &mut sink, before);

`

921

930

`} else {

`

922

931

`break;

`

923

932

`}

`

`@@ -934,26 +943,28 @@ impl<'src> Classifier<'src> {

`

934

943

`&mut self,

`

935

944

`token: TokenKind,

`

936

945

`text: &'src str,

`

937

``

`-

sink: &mut dyn FnMut(Span, Highlight<'src>),

`

``

946

`+

mut sink: impl FnMut(Span, Highlight<'src>),

`

938

947

`before: u32,

`

939

948

`) {

`

940

949

`let lookahead = self.peek();

`

941

950

`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| {

`

946

954

`let mut start = 0u32;

`

947

955

`for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {

`

948

956

`sink(

`

949

957

`new_span(before + start, part, file_span),

`

950

``

`-

Highlight::Token { text: part, class: None },

`

``

958

`+

Highlight::Token { text: part, class },

`

951

959

`);

`

952

960

` start += part.len() as u32;

`

953

961

`}

`

954

962

`};

`

955

963

`let class = match token {

`

956

``

`-

TokenKind::Whitespace => return whitespace(sink),

`

``

964

`+

TokenKind::Whitespace => {

`

``

965

`+

whitespace(None);

`

``

966

`+

return;

`

``

967

`+

}

`

957

968

`TokenKind::LineComment { doc_style } | TokenKind::BlockComment { doc_style, .. } => {

`

958

969

`if doc_style.is_some() {

`

959

970

`Class::DocComment

`

`@@ -974,7 +985,10 @@ impl<'src> Classifier<'src> {

`

974

985

`// or a reference or pointer type. Unless, of course, it looks like

`

975

986

`` // a logical and or a multiplication operator: && or * .

``

976

987

`TokenKind::Star => match self.tokens.peek() {

`

977

``

`-

Some((TokenKind::Whitespace, _)) => return whitespace(sink),

`

``

988

`+

Some((TokenKind::Whitespace, _)) => {

`

``

989

`+

whitespace(None);

`

``

990

`+

return;

`

``

991

`+

}

`

978

992

`Some((TokenKind::Ident, "mut")) => {

`

979

993

`self.next();

`

980

994

`sink(

`

`@@ -1004,7 +1018,10 @@ impl<'src> Classifier<'src> {

`

1004

1018

`sink(DUMMY_SP, Highlight::Token { text: "&=", class: None });

`

1005

1019

`return;

`

1006

1020

`}

`

1007

``

`-

Some((TokenKind::Whitespace, _)) => return whitespace(sink),

`

``

1021

`+

Some((TokenKind::Whitespace, _)) => {

`

``

1022

`+

whitespace(None);

`

``

1023

`+

return;

`

``

1024

`+

}

`

1008

1025

`Some((TokenKind::Ident, "mut")) => {

`

1009

1026

`self.next();

`

1010

1027

`sink(

`

`@@ -1028,7 +1045,11 @@ impl<'src> Classifier<'src> {

`

1028

1045

`sink(DUMMY_SP, Highlight::Token { text: "=>", class: None });

`

1029

1046

`return;

`

1030

1047

`}

`

1031

``

`-

_ => return no_highlight(sink),

`

``

1048

`+

_ => {

`

``

1049

`+

let (span, highlight) = no_highlight();

`

``

1050

`+

sink(span, highlight);

`

``

1051

`+

return;

`

``

1052

`+

}

`

1032

1053

`},

`

1033

1054

`TokenKind::Minus if lookahead == Some(TokenKind::Gt) => {

`

1034

1055

`self.next();

`

`@@ -1045,7 +1066,11 @@ impl<'src> Classifier<'src> {

`

1045

1066

` | TokenKind::Percent

`

1046

1067

` | TokenKind::Bang

`

1047

1068

` | 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

`+

}

`

1049

1074

``

1050

1075

`// Miscellaneous, no highlighting.

`

1051

1076

`TokenKind::Dot

`

`@@ -1060,7 +1085,11 @@ impl<'src> Classifier<'src> {

`

1060

1085

` | TokenKind::Tilde

`

1061

1086

` | TokenKind::Colon

`

1062

1087

` | 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

`+

}

`

1064

1093

``

1065

1094

`TokenKind::Question => Class::QuestionMark,

`

1066

1095

``

`@@ -1069,7 +1098,11 @@ impl<'src> Classifier<'src> {

`

1069

1098

`self.in_macro_nonterminal = true;

`

1070

1099

`Class::MacroNonTerminal

`

1071

1100

`}

`

1072

``

`-

_ => return no_highlight(sink),

`

``

1101

`+

_ => {

`

``

1102

`+

let (span, highlight) = no_highlight();

`

``

1103

`+

sink(span, highlight);

`

``

1104

`+

return;

`

``

1105

`+

}

`

1073

1106

`},

`

1074

1107

``

1075

1108

`// This might be the start of an attribute. We're going to want to

`

`@@ -1100,9 +1133,11 @@ impl<'src> Classifier<'src> {

`

1100

1133

`Highlight::EnterSpan { class: Class::Attribute },

`

1101

1134

`);

`

1102

1135

`}

`

1103

``

`-

_ => (),

`

``

1136

`+

_ => {}

`

1104

1137

`}

`

1105

``

`-

return no_highlight(sink);

`

``

1138

`+

let (span, highlight) = no_highlight();

`

``

1139

`+

sink(span, highlight);

`

``

1140

`+

return;

`

1106

1141

`}

`

1107

1142

`TokenKind::CloseBracket => {

`

1108

1143

`if self.in_attribute {

`

`@@ -1114,7 +1149,9 @@ impl<'src> Classifier<'src> {

`

1114

1149

`sink(DUMMY_SP, Highlight::ExitSpan);

`

1115

1150

`return;

`

1116

1151

`}

`

1117

``

`-

return no_highlight(sink);

`

``

1152

`+

let (span, highlight) = no_highlight();

`

``

1153

`+

sink(span, highlight);

`

``

1154

`+

return;

`

1118

1155

`}

`

1119

1156

`TokenKind::Literal { kind, .. } => match kind {

`

1120

1157

`// Text literals.

`

`@@ -1129,7 +1166,11 @@ impl<'src> Classifier<'src> {

`

1129

1166

`// Number literals.

`

1130

1167

`LiteralKind::Float { .. } | LiteralKind::Int { .. } => Class::Number,

`

1131

1168

`},

`

1132

``

`-

TokenKind::GuardedStrPrefix => return no_highlight(sink),

`

``

1169

`+

TokenKind::GuardedStrPrefix => {

`

``

1170

`+

let (span, highlight) = no_highlight();

`

``

1171

`+

sink(span, highlight);

`

``

1172

`+

return;

`

``

1173

`+

}

`

1133

1174

`TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => {

`

1134

1175

`self.in_macro = true;

`

1135

1176

`let span = new_span(before, text, file_span);

`

`@@ -1165,14 +1206,7 @@ impl<'src> Classifier<'src> {

`

1165

1206

`};

`

1166

1207

`// Anything that didn't return above is the simple case where we the

`

1167

1208

`` // 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));

`

1176

1210

`}

`

1177

1211

``

1178

1212

`fn peek(&mut self) -> Option {

`