@@ -10,6 +10,7 @@ use std::collections::VecDeque;
1010use std:: fmt:: { self , Display , Write } ;
1111use std:: iter;
1212
13+ use arrayvec:: ArrayVec ;
1314use rustc_data_structures:: fx:: FxIndexMap ;
1415use rustc_lexer:: { Cursor , FrontmatterAllowed , LiteralKind , TokenKind } ;
1516use 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