Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/highlight_related.rs')
| -rw-r--r-- | crates/ide/src/highlight_related.rs | 96 |
1 files changed, 76 insertions, 20 deletions
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 80624eeae8..aa947921a9 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -11,7 +11,6 @@ use ide_db::{ preorder_expr_with_ctx_checker, }, }; -use span::FileId; use syntax::{ AstNode, SyntaxKind::{self, IDENT, INT_NUMBER}, @@ -61,13 +60,12 @@ pub(crate) fn highlight_related( let file_id = sema .attach_first_edition(file_id) .unwrap_or_else(|| EditionedFileId::current_edition(sema.db, file_id)); - let span_file_id = file_id.editioned_file_id(sema.db); let syntax = sema.parse(file_id).syntax().clone(); let token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind { T![?] => 4, // prefer `?` when the cursor is sandwiched like in `await$0?` T![->] => 4, - kind if kind.is_keyword(span_file_id.edition()) => 3, + kind if kind.is_keyword(file_id.edition(sema.db)) => 3, IDENT | INT_NUMBER => 2, T![|] => 1, _ => 0, @@ -89,18 +87,14 @@ 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![|] if config.closure_captures => { - highlight_closure_captures(sema, token, file_id, span_file_id.file_id()) + T![unsafe] if token.parent().and_then(ast::BlockExpr::cast).is_some() => { + highlight_unsafe_points(sema, token).remove(&file_id) } - T![move] if config.closure_captures => { - highlight_closure_captures(sema, token, file_id, span_file_id.file_id()) + T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id), + T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id), + _ if config.references => { + highlight_references(sema, token, FilePosition { file_id, offset }) } - _ if config.references => highlight_references( - sema, - token, - FilePosition { file_id, offset }, - span_file_id.file_id(), - ), _ => None, } } @@ -109,7 +103,6 @@ fn highlight_closure_captures( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, file_id: EditionedFileId, - vfs_file_id: FileId, ) -> Option<Vec<HighlightedRange>> { let closure = token.parent_ancestors().take(2).find_map(ast::ClosureExpr::cast)?; let search_range = closure.body()?.syntax().text_range(); @@ -142,7 +135,7 @@ fn highlight_closure_captures( .sources(sema.db) .into_iter() .flat_map(|x| x.to_nav(sema.db)) - .filter(|decl| decl.file_id == vfs_file_id) + .filter(|decl| decl.file_id == file_id.file_id(sema.db)) .filter_map(|decl| decl.focus_range) .map(move |range| HighlightedRange { range, category }) .chain(usages) @@ -155,9 +148,8 @@ fn highlight_references( sema: &Semantics<'_, RootDatabase>, token: SyntaxToken, FilePosition { file_id, offset }: FilePosition, - vfs_file_id: FileId, ) -> Option<Vec<HighlightedRange>> { - let defs = if let Some((range, resolution)) = + let defs = if let Some((range, _, _, resolution)) = sema.check_for_format_args_template(token.clone(), offset) { match resolution.map(Definition::from) { @@ -267,7 +259,7 @@ fn highlight_references( .sources(sema.db) .into_iter() .flat_map(|x| x.to_nav(sema.db)) - .filter(|decl| decl.file_id == vfs_file_id) + .filter(|decl| decl.file_id == file_id.file_id(sema.db)) .filter_map(|decl| decl.focus_range) .map(|range| HighlightedRange { range, category }) .for_each(|x| { @@ -285,7 +277,7 @@ fn highlight_references( }, }; for nav in navs { - if nav.file_id != vfs_file_id { + if nav.file_id != file_id.file_id(sema.db) { continue; } let hl_range = nav.focus_range.map(|range| { @@ -650,7 +642,7 @@ impl<'a> WalkExpandedExprCtx<'a> { expr.macro_call().and_then(|call| self.sema.expand_macro_call(&call)) { match_ast! { - match expanded { + match (expanded.value) { ast::MacroStmts(it) => { self.handle_expanded(it, cb); }, @@ -706,6 +698,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; @@ -755,6 +785,32 @@ mod tests { } #[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( r#" |