Skip to content

Commit f6f92a2

Browse files
committed
feat: highlight unsafe operations
1 parent 40a3f84 commit f6f92a2

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

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

Lines changed: 57 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_ancestors().find_map(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,60 @@ 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: 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+
709766
#[cfg(test)]
710767
mod tests {
711768
use itertools::Itertools;

0 commit comments

Comments
 (0)