Merge pull request #19687 from gohome001/highlight_unsafe

feat: highlight unsafe operations
This commit is contained in:
Lukas Wirth 2025-05-18 08:44:10 +00:00 committed by GitHub
commit 7e4bbe1f6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -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().and_then(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,44 @@ impl<'a> WalkExpandedExprCtx<'a> {
}
}
pub(crate) fn highlight_unsafe_points(
sema: &Semantics<'_, RootDatabase>,
token: SyntaxToken,
) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
fn hl(
sema: &Semantics<'_, RootDatabase>,
unsafe_token: &SyntaxToken,
block_expr: Option<ast::BlockExpr>,
) -> Option<FxHashMap<EditionedFileId, Vec<HighlightedRange>>> {
let mut highlights: FxHashMap<EditionedFileId, Vec<_>> = 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_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(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()));
}
}
}
Some(highlights)
}
hl(sema, &token, token.parent().and_then(ast::BlockExpr::cast)).unwrap_or_default()
}
#[cfg(test)]
mod tests {
use itertools::Itertools;
@ -754,6 +795,32 @@ 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(