@@ -89,6 +89,9 @@ pub(crate) fn highlight_related(
89
89
T ! [ break ] | T ! [ loop ] | T ! [ while ] | T ! [ continue ] if config. break_points => {
90
90
highlight_break_points ( sema, token) . remove ( & file_id)
91
91
}
92
+ T ! [ unsafe ] if token. parent ( ) . and_then ( ast:: BlockExpr :: cast) . is_some ( ) => {
93
+ highlight_unsafe_points ( sema, token) . remove ( & file_id)
94
+ }
92
95
T ! [ |] if config. closure_captures => {
93
96
highlight_closure_captures ( sema, token, file_id, span_file_id. file_id ( ) )
94
97
}
@@ -706,6 +709,44 @@ impl<'a> WalkExpandedExprCtx<'a> {
706
709
}
707
710
}
708
711
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
+
709
750
#[ cfg( test) ]
710
751
mod tests {
711
752
use itertools:: Itertools ;
@@ -754,6 +795,32 @@ mod tests {
754
795
assert_eq ! ( expected, actual) ;
755
796
}
756
797
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
+
757
824
#[ test]
758
825
fn test_hl_tuple_fields ( ) {
759
826
check (
0 commit comments