@@ -832,6 +832,20 @@ impl<'a> PeekIter<'a> {
832832 . copied ( )
833833 }
834834
835+ fn peek_next_if < F : Fn ( ( TokenKind , & ' a str ) ) -> bool > (
836+ & mut self ,
837+ f : F ,
838+ ) -> Option < ( TokenKind , & ' a str ) > {
839+ let next = self . peek_next ( ) ?;
840+ if f ( next) {
841+ Some ( next)
842+ } else {
843+ // We go one step back.
844+ self . peek_pos -= 1 ;
845+ None
846+ }
847+ }
848+
835849 fn stop_peeking ( & mut self ) {
836850 self . peek_pos = 0 ;
837851 }
@@ -903,18 +917,19 @@ fn classify<'src>(
903917 }
904918 }
905919
906- if let Some ( ( TokenKind :: Colon | TokenKind :: Ident , _) ) = classifier. tokens . peek ( ) {
907- let tokens = classifier. get_full_ident_path ( ) ;
908- for & ( token , start , end ) in & tokens {
909- let text = & classifier. src [ start..end ] ;
910- classifier . advance ( token , text , sink , start as u32 ) ;
911- classifier . byte_pos += text . len ( ) as u32 ;
912- }
913- if !tokens . is_empty ( ) {
914- continue ;
920+ if let Some ( ( TokenKind :: Colon | TokenKind :: Ident , _) ) = classifier. tokens . peek ( )
921+ && let Some ( nb_items ) = classifier. get_full_ident_path ( )
922+ {
923+ let start = classifier. byte_pos as usize ;
924+ let mut len = 0 ;
925+ for _ in 0 ..nb_items {
926+ if let Some ( ( _ , text , _ ) ) = classifier . next ( ) {
927+ len += text . len ( ) ;
928+ }
915929 }
916- }
917- if let Some ( ( token, text, before) ) = classifier. next ( ) {
930+ let text = & classifier. src [ start..start + len] ;
931+ classifier. advance ( TokenKind :: Ident , text, sink, start as u32 ) ;
932+ } else if let Some ( ( token, text, before) ) = classifier. next ( ) {
918933 classifier. advance ( token, text, sink, before) ;
919934 } else {
920935 break ;
@@ -957,47 +972,47 @@ impl<'src> Classifier<'src> {
957972 }
958973
959974 /// Concatenate colons and idents as one when possible.
960- fn get_full_ident_path ( & mut self ) -> Vec < ( TokenKind , usize , usize ) > {
961- let start = self . byte_pos as usize ;
962- let mut pos = start;
975+ fn get_full_ident_path ( & mut self ) -> Option < usize > {
963976 let mut has_ident = false ;
977+ let mut nb_items = 0 ;
964978
965- loop {
979+ let ret = loop {
966980 let mut nb = 0 ;
967- while let Some ( ( TokenKind :: Colon , _) ) = self . tokens . peek ( ) {
968- self . tokens . next ( ) ;
981+ while self . tokens . peek_next_if ( |( token, _) | token == TokenKind :: Colon ) . is_some ( ) {
969982 nb += 1 ;
983+ nb_items += 1 ;
970984 }
971985 // Ident path can start with "::" but if we already have content in the ident path,
972986 // the "::" is mandatory.
973987 if has_ident && nb == 0 {
974- return vec ! [ ( TokenKind :: Ident , start , pos ) ] ;
988+ break Some ( nb_items ) ;
975989 } else if nb != 0 && nb != 2 {
976990 if has_ident {
977- return vec ! [ ( TokenKind :: Ident , start, pos) , ( TokenKind :: Colon , pos, pos + nb) ] ;
991+ // Following `;` will be handled on its own.
992+ break Some ( nb_items - 1 ) ;
978993 } else {
979- return vec ! [ ( TokenKind :: Colon , start , pos + nb ) ] ;
994+ break None ;
980995 }
981996 }
982997
983- if let Some ( ( TokenKind :: Ident , text) ) = self . tokens . peek ( )
998+ if let Some ( ( TokenKind :: Ident , text) ) =
999+ self . tokens . peek_next_if ( |( token, _) | token == TokenKind :: Ident )
9841000 && let symbol = Symbol :: intern ( text)
9851001 && ( symbol. is_path_segment_keyword ( ) || !is_keyword ( symbol) )
9861002 {
987- // We only "add" the colon if there is an ident behind.
988- pos += text. len ( ) + nb;
9891003 has_ident = true ;
990- self . tokens . next ( ) ;
1004+ nb_items += 1 ;
9911005 } else if nb > 0 && has_ident {
992- return vec ! [ ( TokenKind :: Ident , start, pos) , ( TokenKind :: Colon , pos, pos + nb) ] ;
993- } else if nb > 0 {
994- return vec ! [ ( TokenKind :: Colon , start, start + nb) ] ;
1006+ // Following `;` will be handled on its own.
1007+ break Some ( nb_items - 1 ) ;
9951008 } else if has_ident {
996- return vec ! [ ( TokenKind :: Ident , start , pos ) ] ;
1009+ break Some ( nb_items ) ;
9971010 } else {
998- return Vec :: new ( ) ;
1011+ break None ;
9991012 }
1000- }
1013+ } ;
1014+ self . tokens . stop_peeking ( ) ;
1015+ ret
10011016 }
10021017
10031018 /// Wraps the tokens iteration to ensure that the `byte_pos` is always correct.
@@ -1243,7 +1258,6 @@ impl<'src> Classifier<'src> {
12431258 Class :: MacroNonTerminal
12441259 }
12451260 TokenKind :: Ident => {
1246- let file_span = self . file_span ;
12471261 let span = || new_span ( before, text, file_span) ;
12481262
12491263 match text {
0 commit comments