@@ -89,6 +89,9 @@ pub(crate) fn highlight_related(
8989 T ! [ break ] | T ! [ loop ] | T ! [ while ] | T ! [ continue ] if config. break_points => {
9090 highlight_break_points ( sema, token) . remove ( & file_id)
9191 }
92+ T ! [ unsafe ] if token. parent_ancestors ( ) . find_map ( ast:: BlockExpr :: cast) . is_some ( ) => {
93+ highlight_unsafe_points ( sema, token) . remove ( & file_id)
94+ }
9295 T ! [ |] if config. closure_captures => {
9396 highlight_closure_captures ( sema, token, file_id, span_file_id. file_id ( ) )
9497 }
@@ -706,6 +709,60 @@ impl<'a> WalkExpandedExprCtx<'a> {
706709 }
707710}
708711
712+ pub ( crate ) fn highlight_unsafe_points (
713+ sema : & Semantics < ' _ , RootDatabase > ,
714+ token : SyntaxToken ,
715+ ) -> FxHashMap < EditionedFileId , Vec < HighlightedRange > > {
716+ fn hl (
717+ sema : & Semantics < ' _ , RootDatabase > ,
718+ unsafe_token : Option < SyntaxToken > ,
719+ block_expr : Option < ast:: BlockExpr > ,
720+ ) -> Option < FxHashMap < EditionedFileId , Vec < HighlightedRange > > > {
721+ let mut highlights: FxHashMap < EditionedFileId , Vec < _ > > = FxHashMap :: default ( ) ;
722+
723+ let mut push_to_highlights = |file_id, range| {
724+ if let Some ( FileRange { file_id, range } ) = original_frange ( sema. db , file_id, range) {
725+ let hrange = HighlightedRange { category : ReferenceCategory :: empty ( ) , range } ;
726+ highlights. entry ( file_id) . or_default ( ) . push ( hrange) ;
727+ }
728+ } ;
729+
730+ // highlight unsafe keyword itself
731+ let unsafe_token = unsafe_token?;
732+ let unsafe_token_file_id = sema. hir_file_for ( & unsafe_token. parent ( ) ?) ;
733+ push_to_highlights ( unsafe_token_file_id, Some ( unsafe_token. text_range ( ) ) ) ;
734+
735+ if let Some ( block) = block_expr {
736+ if let Some ( node) = block. syntax ( ) . ancestors ( ) . find ( |n| ast:: Fn :: can_cast ( n. kind ( ) ) ) {
737+ if let Some ( function) = ast:: Fn :: cast ( node) {
738+ // highlight unsafe keyword of the function
739+ if let Some ( unsafe_token) = function. unsafe_token ( ) {
740+ push_to_highlights ( unsafe_token_file_id, Some ( unsafe_token. text_range ( ) ) ) ;
741+ }
742+ // highlight unsafe operations
743+ if let Some ( f) = sema. to_def ( & function) {
744+ let unsafe_ops = sema. get_unsafe_ops ( f. into ( ) ) ;
745+ for unsafe_op in unsafe_ops {
746+ push_to_highlights (
747+ unsafe_op. file_id ,
748+ Some ( unsafe_op. value . text_range ( ) ) ,
749+ ) ;
750+ }
751+ }
752+ }
753+ }
754+ }
755+
756+ Some ( highlights)
757+ }
758+
759+ let Some ( block_expr) = token. parent ( ) . and_then ( ast:: BlockExpr :: cast) else {
760+ return FxHashMap :: default ( ) ;
761+ } ;
762+
763+ hl ( sema, Some ( token) , Some ( block_expr) ) . unwrap_or_default ( )
764+ }
765+
709766#[ cfg( test) ]
710767mod tests {
711768 use itertools:: Itertools ;
0 commit comments