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.rs96
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#"