@@ -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 ( ) . and_then ( 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,44 @@ 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 : & 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_file_id = sema. hir_file_for ( & unsafe_token. parent ( ) ?) ;
732+ push_to_highlights ( unsafe_token_file_id, Some ( unsafe_token. text_range ( ) ) ) ;
733+
734+ // highlight unsafe operations
735+ if let Some ( block) = block_expr {
736+ if let Some ( body) = sema. body_for ( InFile :: new ( unsafe_token_file_id, block. syntax ( ) ) ) {
737+ let unsafe_ops = sema. get_unsafe_ops ( body) ;
738+ for unsafe_op in unsafe_ops {
739+ push_to_highlights ( unsafe_op. file_id , Some ( unsafe_op. value . text_range ( ) ) ) ;
740+ }
741+ }
742+ }
743+
744+ Some ( highlights)
745+ }
746+
747+ hl ( sema, & token, token. parent ( ) . and_then ( ast:: BlockExpr :: cast) ) . unwrap_or_default ( )
748+ }
749+
709750#[ cfg( test) ]
710751mod tests {
711752 use itertools:: Itertools ;
@@ -754,6 +795,32 @@ mod tests {
754795 assert_eq ! ( expected, actual) ;
755796 }
756797
798+ #[ test]
799+ fn test_hl_unsafe_block ( ) {
800+ check (
801+ r#"
802+ fn foo() {
803+ unsafe fn this_is_unsafe_function() {}
804+
805+ unsa$0fe {
806+ //^^^^^^
807+ let raw_ptr = &42 as *const i32;
808+ let val = *raw_ptr;
809+ //^^^^^^^^
810+
811+ let mut_ptr = &mut 5 as *mut i32;
812+ *mut_ptr = 10;
813+ //^^^^^^^^
814+
815+ this_is_unsafe_function();
816+ //^^^^^^^^^^^^^^^^^^^^^^^^^
817+ }
818+
819+ }
820+ "# ,
821+ ) ;
822+ }
823+
757824 #[ test]
758825 fn test_hl_tuple_fields ( ) {
759826 check (
0 commit comments