@@ -823,15 +823,31 @@ impl<'a> PeekIter<'a> {
823823 self . peek_pos += 1 ;
824824 if self . peek_pos - 1 < self . stored . len ( ) {
825825 self . stored . get ( self . peek_pos - 1 )
826- } else if let Some ( next) = self . iter . next ( ) {
827- self . stored . push_back ( next) ;
828- self . stored . back ( )
829826 } else {
830- None
827+ if let Some ( next) = self . iter . next ( ) {
828+ self . stored . push_back ( next) ;
829+ self . stored . back ( )
830+ } else {
831+ None
832+ }
831833 }
832834 . copied ( )
833835 }
834836
837+ fn peek_next_if < F : Fn ( ( TokenKind , & ' a str ) ) -> bool > (
838+ & mut self ,
839+ f : F ,
840+ ) -> Option < ( TokenKind , & ' a str ) > {
841+ let next = self . peek_next ( ) ?;
842+ if f ( next) {
843+ Some ( next)
844+ } else {
845+ // We go one step back.
846+ self . peek_pos -= 1 ;
847+ None
848+ }
849+ }
850+
835851 fn stop_peeking ( & mut self ) {
836852 self . peek_pos = 0 ;
837853 }
@@ -903,18 +919,19 @@ fn classify<'src>(
903919 }
904920 }
905921
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 ;
922+ if let Some ( ( TokenKind :: Colon | TokenKind :: Ident , _) ) = classifier. tokens . peek ( )
923+ && let Some ( nb_items ) = classifier. get_full_ident_path ( )
924+ {
925+ let start = classifier. byte_pos as usize ;
926+ let mut len = 0 ;
927+ for _ in 0 ..nb_items {
928+ if let Some ( ( _ , text , _ ) ) = classifier . next ( ) {
929+ len += text . len ( ) ;
930+ }
915931 }
916- }
917- if let Some ( ( token, text, before) ) = classifier. next ( ) {
932+ let text = & classifier. src [ start..start + len] ;
933+ classifier. advance ( TokenKind :: Ident , text, sink, start as u32 ) ;
934+ } else if let Some ( ( token, text, before) ) = classifier. next ( ) {
918935 classifier. advance ( token, text, sink, before) ;
919936 } else {
920937 break ;
@@ -957,47 +974,47 @@ impl<'src> Classifier<'src> {
957974 }
958975
959976 /// 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;
977+ fn get_full_ident_path ( & mut self ) -> Option < usize > {
963978 let mut has_ident = false ;
979+ let mut nb_items = 0 ;
964980
965- loop {
981+ let ret = loop {
966982 let mut nb = 0 ;
967- while let Some ( ( TokenKind :: Colon , _) ) = self . tokens . peek ( ) {
968- self . tokens . next ( ) ;
983+ while self . tokens . peek_next_if ( |( token, _) | token == TokenKind :: Colon ) . is_some ( ) {
969984 nb += 1 ;
985+ nb_items += 1 ;
970986 }
971987 // Ident path can start with "::" but if we already have content in the ident path,
972988 // the "::" is mandatory.
973989 if has_ident && nb == 0 {
974- return vec ! [ ( TokenKind :: Ident , start , pos ) ] ;
990+ break Some ( nb_items ) ;
975991 } else if nb != 0 && nb != 2 {
976992 if has_ident {
977- return vec ! [ ( TokenKind :: Ident , start, pos) , ( TokenKind :: Colon , pos, pos + nb) ] ;
993+ // Following `;` will be handled on its own.
994+ break Some ( nb_items - 1 ) ;
978995 } else {
979- return vec ! [ ( TokenKind :: Colon , start , pos + nb ) ] ;
996+ break None ;
980997 }
981998 }
982999
983- if let Some ( ( TokenKind :: Ident , text) ) = self . tokens . peek ( )
1000+ if let Some ( ( TokenKind :: Ident , text) ) =
1001+ self . tokens . peek_next_if ( |( token, _) | token == TokenKind :: Ident )
9841002 && let symbol = Symbol :: intern ( text)
9851003 && ( symbol. is_path_segment_keyword ( ) || !is_keyword ( symbol) )
9861004 {
987- // We only "add" the colon if there is an ident behind.
988- pos += text. len ( ) + nb;
9891005 has_ident = true ;
990- self . tokens . next ( ) ;
1006+ nb_items += 1 ;
9911007 } 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) ] ;
1008+ // Following `;` will be handled on its own.
1009+ break Some ( nb_items - 1 ) ;
9951010 } else if has_ident {
996- return vec ! [ ( TokenKind :: Ident , start , pos ) ] ;
1011+ break Some ( nb_items ) ;
9971012 } else {
998- return Vec :: new ( ) ;
1013+ break None ;
9991014 }
1000- }
1015+ } ;
1016+ self . tokens . stop_peeking ( ) ;
1017+ ret
10011018 }
10021019
10031020 /// Wraps the tokens iteration to ensure that the `byte_pos` is always correct.
@@ -1243,7 +1260,6 @@ impl<'src> Classifier<'src> {
12431260 Class :: MacroNonTerminal
12441261 }
12451262 TokenKind :: Ident => {
1246- let file_span = self . file_span ;
12471263 let span = || new_span ( before, text, file_span) ;
12481264
12491265 match text {
0 commit comments