From 0d1743a890e1e56d7625da9b277ddd2cf4588f7c Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Fri, 25 Apr 2025 15:59:11 +0800 Subject: [PATCH 1/4] feat: highlight unsafe operations --- crates/ide/src/highlight_related.rs | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 80624eeae8..750ad23026 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -89,6 +89,9 @@ pub(crate) fn highlight_related( T![break] | T![loop] | T![while] | T![continue] if config.break_points => { highlight_break_points(sema, token).remove(&file_id) } + T![unsafe] if token.parent_ancestors().find_map(ast::BlockExpr::cast).is_some() => { + highlight_unsafe_points(sema, token).remove(&file_id) + } T![|] if config.closure_captures => { highlight_closure_captures(sema, token, file_id, span_file_id.file_id()) } @@ -706,6 +709,60 @@ impl<'a> WalkExpandedExprCtx<'a> { } } +pub(crate) fn highlight_unsafe_points( + sema: &Semantics<'_, RootDatabase>, + token: SyntaxToken, +) -> FxHashMap> { + fn hl( + sema: &Semantics<'_, RootDatabase>, + unsafe_token: Option, + block_expr: Option, + ) -> Option>> { + let mut highlights: FxHashMap> = FxHashMap::default(); + + let mut push_to_highlights = |file_id, range| { + if let Some(FileRange { file_id, range }) = original_frange(sema.db, file_id, range) { + let hrange = HighlightedRange { category: ReferenceCategory::empty(), range }; + highlights.entry(file_id).or_default().push(hrange); + } + }; + + // highlight unsafe keyword itself + let unsafe_token = unsafe_token?; + let unsafe_token_file_id = sema.hir_file_for(&unsafe_token.parent()?); + push_to_highlights(unsafe_token_file_id, Some(unsafe_token.text_range())); + + if let Some(block) = block_expr { + if let Some(node) = block.syntax().ancestors().find(|n| ast::Fn::can_cast(n.kind())) { + if let Some(function) = ast::Fn::cast(node) { + // highlight unsafe keyword of the function + if let Some(unsafe_token) = function.unsafe_token() { + push_to_highlights(unsafe_token_file_id, Some(unsafe_token.text_range())); + } + // highlight unsafe operations + if let Some(f) = sema.to_def(&function) { + let unsafe_ops = sema.get_unsafe_ops(f.into()); + for unsafe_op in unsafe_ops { + push_to_highlights( + unsafe_op.file_id, + Some(unsafe_op.value.text_range()), + ); + } + } + } + } + } + + Some(highlights) + } + + let Some(block_expr) = token.parent().and_then(ast::BlockExpr::cast) else { + return FxHashMap::default(); + }; + + hl(sema, Some(token), Some(block_expr)).unwrap_or_default() +} + #[cfg(test)] mod tests { use itertools::Itertools; From e525239877105783e1b285450283b73322ecb41c Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Fri, 25 Apr 2025 16:01:20 +0800 Subject: [PATCH 2/4] test: add test case for highlight unsafe operations --- crates/ide/src/highlight_related.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 750ad23026..2943d60682 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -811,6 +811,34 @@ mod tests { assert_eq!(expected, actual); } + #[test] + fn test_hl_unsafe_block() { + check( + r#" +fn foo() { + unsafe fn this_is_unsafe_function() { + } + + + unsa$0fe { + //^^^^^^ + let raw_ptr = &42 as *const i32; + let val = *raw_ptr; + //^^^^^^^^ + + let mut_ptr = &mut 5 as *mut i32; + *mut_ptr = 10; + //^^^^^^^^ + + this_is_unsafe_function(); + //^^^^^^^^^^^^^^^^^^^^^^^^^ + } + +} +"#, + ); + } + #[test] fn test_hl_tuple_fields() { check( From 1d4602e2b08997e2c555fb5f00f9c816fcce6738 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Fri, 25 Apr 2025 17:02:08 +0800 Subject: [PATCH 3/4] minor: format --- crates/ide/src/highlight_related.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 2943d60682..90a7c62d71 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -816,24 +816,22 @@ mod tests { check( r#" fn foo() { - unsafe fn this_is_unsafe_function() { - } + unsafe fn this_is_unsafe_function() {} - unsa$0fe { //^^^^^^ let raw_ptr = &42 as *const i32; let val = *raw_ptr; //^^^^^^^^ - + let mut_ptr = &mut 5 as *mut i32; *mut_ptr = 10; //^^^^^^^^ - + this_is_unsafe_function(); //^^^^^^^^^^^^^^^^^^^^^^^^^ } - + } "#, ); From c6e3a4cf20a3eea56f6c3944db74d42bd4f96d55 Mon Sep 17 00:00:00 2001 From: gohome001 <3156514693@qq.com> Date: Sat, 10 May 2025 13:16:34 +0800 Subject: [PATCH 4/4] minor: code review tweak --- crates/ide/src/highlight_related.rs | 32 ++++++++--------------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 90a7c62d71..fb8dbcfc73 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -89,7 +89,7 @@ pub(crate) fn highlight_related( T![break] | T![loop] | T![while] | T![continue] if config.break_points => { highlight_break_points(sema, token).remove(&file_id) } - T![unsafe] if token.parent_ancestors().find_map(ast::BlockExpr::cast).is_some() => { + T![unsafe] if token.parent().and_then(ast::BlockExpr::cast).is_some() => { highlight_unsafe_points(sema, token).remove(&file_id) } T![|] if config.closure_captures => { @@ -715,7 +715,7 @@ pub(crate) fn highlight_unsafe_points( ) -> FxHashMap> { fn hl( sema: &Semantics<'_, RootDatabase>, - unsafe_token: Option, + unsafe_token: &SyntaxToken, block_expr: Option, ) -> Option>> { let mut highlights: FxHashMap> = FxHashMap::default(); @@ -728,27 +728,15 @@ pub(crate) fn highlight_unsafe_points( }; // highlight unsafe keyword itself - let unsafe_token = unsafe_token?; let unsafe_token_file_id = sema.hir_file_for(&unsafe_token.parent()?); push_to_highlights(unsafe_token_file_id, Some(unsafe_token.text_range())); + // highlight unsafe operations if let Some(block) = block_expr { - if let Some(node) = block.syntax().ancestors().find(|n| ast::Fn::can_cast(n.kind())) { - if let Some(function) = ast::Fn::cast(node) { - // highlight unsafe keyword of the function - if let Some(unsafe_token) = function.unsafe_token() { - push_to_highlights(unsafe_token_file_id, Some(unsafe_token.text_range())); - } - // highlight unsafe operations - if let Some(f) = sema.to_def(&function) { - let unsafe_ops = sema.get_unsafe_ops(f.into()); - for unsafe_op in unsafe_ops { - push_to_highlights( - unsafe_op.file_id, - Some(unsafe_op.value.text_range()), - ); - } - } + if let Some(body) = sema.body_for(InFile::new(unsafe_token_file_id, block.syntax())) { + let unsafe_ops = sema.get_unsafe_ops(body); + for unsafe_op in unsafe_ops { + push_to_highlights(unsafe_op.file_id, Some(unsafe_op.value.text_range())); } } } @@ -756,11 +744,7 @@ pub(crate) fn highlight_unsafe_points( Some(highlights) } - let Some(block_expr) = token.parent().and_then(ast::BlockExpr::cast) else { - return FxHashMap::default(); - }; - - hl(sema, Some(token), Some(block_expr)).unwrap_or_default() + hl(sema, &token, token.parent().and_then(ast::BlockExpr::cast)).unwrap_or_default() } #[cfg(test)]