@@ -754,21 +754,6 @@ impl<'a> Iterator for TokenIter<'a> {
754754 }
755755}
756756
757- /// Classifies into identifier class; returns `None` if this is a non-keyword identifier.
758- fn get_real_ident_class ( text : & str , allow_path_keywords : bool ) -> Option < Class > {
759- let ignore: & [ & str ] =
760- if allow_path_keywords { & [ "self" , "Self" , "super" , "crate" ] } else { & [ "self" , "Self" ] } ;
761- if ignore. contains ( & text) {
762- return None ;
763- }
764- Some ( match text {
765- "ref" | "mut" => Class :: RefKeyWord ,
766- "false" | "true" => Class :: Bool ,
767- _ if Symbol :: intern ( text) . is_reserved ( || Edition :: Edition2021 ) => Class :: KeyWord ,
768- _ => return None ,
769- } )
770- }
771-
772757/// This iterator comes from the same idea than "Peekable" except that it allows to "peek" more than
773758/// just the next item by using `peek_next`. The `peek` method always returns the next item after
774759/// the current one whereas `peek_next` will return the next item after the last one peeked.
@@ -786,16 +771,16 @@ impl<'a> PeekIter<'a> {
786771 Self { stored : VecDeque :: new ( ) , peek_pos : 0 , iter }
787772 }
788773 /// Returns the next item after the current one. It doesn't interfere with `peek_next` output.
789- fn peek ( & mut self ) -> Option < & ( TokenKind , & ' a str ) > {
774+ fn peek ( & mut self ) -> Option < ( TokenKind , & ' a str ) > {
790775 if self . stored . is_empty ( )
791776 && let Some ( next) = self . iter . next ( )
792777 {
793778 self . stored . push_back ( next) ;
794779 }
795- self . stored . front ( )
780+ self . stored . front ( ) . copied ( )
796781 }
797782 /// Returns the next item after the last one peeked. It doesn't interfere with `peek` output.
798- fn peek_next ( & mut self ) -> Option < & ( TokenKind , & ' a str ) > {
783+ fn peek_next ( & mut self ) -> Option < ( TokenKind , & ' a str ) > {
799784 self . peek_pos += 1 ;
800785 if self . peek_pos - 1 < self . stored . len ( ) {
801786 self . stored . get ( self . peek_pos - 1 )
@@ -805,6 +790,7 @@ impl<'a> PeekIter<'a> {
805790 } else {
806791 None
807792 }
793+ . copied ( )
808794 }
809795
810796 fn stop_peeking ( & mut self ) {
@@ -951,15 +937,9 @@ impl<'src> Classifier<'src> {
951937 }
952938 }
953939
954- if let Some ( ( None , text) ) = self . tokens . peek ( ) . map ( |( token, text) | {
955- if * token == TokenKind :: Ident {
956- let class = get_real_ident_class ( text, true ) ;
957- ( class, text)
958- } else {
959- // Doesn't matter which Class we put in here...
960- ( Some ( Class :: Comment ) , text)
961- }
962- } ) {
940+ if let Some ( ( TokenKind :: Ident , text) ) = self . tokens . peek ( )
941+ && !ident_is_keyword ( text)
942+ {
963943 // We only "add" the colon if there is an ident behind.
964944 pos += text. len ( ) + nb;
965945 has_ident = true ;
@@ -1197,34 +1177,15 @@ impl<'src> Classifier<'src> {
11971177 } ,
11981178 TokenKind :: GuardedStrPrefix => return no_highlight ( sink) ,
11991179 TokenKind :: Ident | TokenKind :: RawIdent
1200- if self . peek_non_whitespace ( ) == Some ( TokenKind :: Bang ) =>
1180+ if let Some ( ( TokenKind :: Bang , _ ) ) = self . peek_non_trivia ( ) =>
12011181 {
12021182 self . in_macro = true ;
12031183 let span = new_span ( before, text, file_span) ;
12041184 sink ( DUMMY_SP , Highlight :: EnterSpan { class : Class :: Macro ( span) } ) ;
12051185 sink ( span, Highlight :: Token { text, class : None } ) ;
12061186 return ;
12071187 }
1208- TokenKind :: Ident => {
1209- match get_real_ident_class ( text, false ) {
1210- None => match text {
1211- "Option" | "Result" => Class :: PreludeTy ( new_span ( before, text, file_span) ) ,
1212- "Some" | "None" | "Ok" | "Err" => {
1213- Class :: PreludeVal ( new_span ( before, text, file_span) )
1214- }
1215- // "union" is a weak keyword and is only considered as a keyword when declaring
1216- // a union type.
1217- "union" if self . check_if_is_union_keyword ( ) => Class :: KeyWord ,
1218- _ if self . in_macro_nonterminal => {
1219- self . in_macro_nonterminal = false ;
1220- Class :: MacroNonTerminal
1221- }
1222- "self" | "Self" => Class :: Self_ ( new_span ( before, text, file_span) ) ,
1223- _ => Class :: Ident ( new_span ( before, text, file_span) ) ,
1224- } ,
1225- Some ( c) => c,
1226- }
1227- }
1188+ TokenKind :: Ident => self . classify_ident ( before, text) ,
12281189 TokenKind :: RawIdent | TokenKind :: UnknownPrefix | TokenKind :: InvalidIdent => {
12291190 Class :: Ident ( new_span ( before, text, file_span) )
12301191 }
@@ -1245,25 +1206,62 @@ impl<'src> Classifier<'src> {
12451206 }
12461207 }
12471208
1209+ fn classify_ident ( & mut self , before : u32 , text : & ' src str ) -> Class {
1210+ // Macro non-terminals (meta vars) take precedence.
1211+ if self . in_macro_nonterminal {
1212+ self . in_macro_nonterminal = false ;
1213+ return Class :: MacroNonTerminal ;
1214+ }
1215+
1216+ let file_span = self . file_span ;
1217+ let span = || new_span ( before, text, file_span) ;
1218+
1219+ match text {
1220+ "ref" | "mut" => Class :: RefKeyWord ,
1221+ "false" | "true" => Class :: Bool ,
1222+ "self" | "Self" => Class :: Self_ ( span ( ) ) ,
1223+ "Option" | "Result" => Class :: PreludeTy ( span ( ) ) ,
1224+ "Some" | "None" | "Ok" | "Err" => Class :: PreludeVal ( span ( ) ) ,
1225+ _ if ident_is_keyword ( text) || self . ident_is_weak_keyword ( text) => Class :: KeyWord ,
1226+ _ => Class :: Ident ( span ( ) ) ,
1227+ }
1228+ }
1229+
1230+ fn ident_is_weak_keyword ( & mut self , text : & str ) -> bool {
1231+ let matches = match text {
1232+ "auto" => |text| text == "trait" , // `auto trait Trait {}` (`auto_traits`)
1233+ "pin" => |text| text == "const" || text == "mut" , // `&pin mut Type` (`pin_ergonomics`)
1234+ "raw" => |text| text == "const" || text == "mut" , // `&raw const local`
1235+ "safe" => |text| text == "fn" || text == "extern" , // `unsafe extern { safe fn f(); }`
1236+ "union" => |_| true , // `union Untagged { field: () }`
1237+ _ => return false ,
1238+ } ;
1239+ matches ! ( self . peek_non_trivia( ) , Some ( ( TokenKind :: Ident , text) ) if matches( text) )
1240+ }
1241+
12481242 fn peek ( & mut self ) -> Option < TokenKind > {
1249- self . tokens . peek ( ) . map ( |( token_kind , _text ) | * token_kind )
1243+ self . tokens . peek ( ) . map ( |( kind , _ ) | kind )
12501244 }
12511245
1252- fn peek_non_whitespace ( & mut self ) -> Option < TokenKind > {
1253- while let Some ( ( token_kind, _) ) = self . tokens . peek_next ( ) {
1254- if * token_kind != TokenKind :: Whitespace {
1255- let token_kind = * token_kind;
1256- self . tokens . stop_peeking ( ) ;
1257- return Some ( token_kind) ;
1246+ fn peek_non_trivia ( & mut self ) -> Option < ( TokenKind , & str ) > {
1247+ while let Some ( token @ ( kind, _) ) = self . tokens . peek_next ( ) {
1248+ if let TokenKind :: Whitespace
1249+ | TokenKind :: LineComment { doc_style : None }
1250+ | TokenKind :: BlockComment { doc_style : None , .. } = kind
1251+ {
1252+ continue ;
12581253 }
1254+ self . tokens . stop_peeking ( ) ;
1255+ return Some ( token) ;
12591256 }
12601257 self . tokens . stop_peeking ( ) ;
12611258 None
12621259 }
1260+ }
12631261
1264- fn check_if_is_union_keyword ( & mut self ) -> bool {
1265- self . peek_non_whitespace ( ) . is_some_and ( |kind| kind == TokenKind :: Ident )
1266- }
1262+ fn ident_is_keyword ( text : & str ) -> bool {
1263+ // FIXME(#148221): Don't hard-code the edition. The classifier should take it as an argument.
1264+ Symbol :: intern ( text ) . is_reserved ( || Edition :: Edition2024 )
12671265}
12681266
12691267fn generate_link_to_def (
0 commit comments