@@ -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_ancestors ( ) . find_map ( 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,60 @@ 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 : 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
+
709
766
#[ cfg( test) ]
710
767
mod tests {
711
768
use itertools:: Itertools ;
0 commit comments