Skip to content

Commit 7e4bbe1

Browse files
authored
Merge pull request #19687 from gohome001/highlight_unsafe
feat: highlight unsafe operations
2 parents 1d073db + 0092abd commit 7e4bbe1

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

src/tools/rust-analyzer/crates/ide/src/highlight_related.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)]
710751
mod 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

Comments
 (0)