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 | 120 |
1 files changed, 98 insertions, 22 deletions
diff --git a/crates/ide/src/highlight_related.rs b/crates/ide/src/highlight_related.rs index 6463206596..80624eeae8 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -1,7 +1,8 @@ use std::iter; -use hir::{db, FilePosition, FileRange, HirFileId, InFile, Semantics}; +use hir::{EditionedFileId, FilePosition, FileRange, HirFileId, InFile, Semantics, db}; use ide_db::{ + FxHashMap, FxHashSet, RootDatabase, defs::{Definition, IdentClass}, helpers::pick_best_token, search::{FileReference, ReferenceCategory, SearchScope}, @@ -9,17 +10,17 @@ use ide_db::{ eq_label_lt, for_each_tail_expr, full_path_of_name_ref, is_closure_or_blk_with_modif, preorder_expr_with_ctx_checker, }, - FxHashMap, FxHashSet, RootDatabase, }; -use span::EditionedFileId; +use span::FileId; use syntax::{ - ast::{self, HasLoopBody}, - match_ast, AstNode, + AstNode, SyntaxKind::{self, IDENT, INT_NUMBER}, - SyntaxToken, TextRange, WalkEvent, T, + SyntaxToken, T, TextRange, WalkEvent, + ast::{self, HasLoopBody}, + match_ast, }; -use crate::{goto_definition, navigation_target::ToNav, NavigationTarget, TryToNav}; +use crate::{NavigationTarget, TryToNav, goto_definition, navigation_target::ToNav}; #[derive(PartialEq, Eq, Hash)] pub struct HighlightedRange { @@ -59,13 +60,14 @@ pub(crate) fn highlight_related( let _p = tracing::info_span!("highlight_related").entered(); let file_id = sema .attach_first_edition(file_id) - .unwrap_or_else(|| EditionedFileId::current_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(file_id.edition()) => 3, + kind if kind.is_keyword(span_file_id.edition()) => 3, IDENT | INT_NUMBER => 2, T![|] => 1, _ => 0, @@ -87,11 +89,18 @@ 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), - T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id), - _ if config.references => { - highlight_references(sema, token, FilePosition { file_id, offset }) + T![|] if config.closure_captures => { + highlight_closure_captures(sema, token, file_id, span_file_id.file_id()) + } + T![move] if config.closure_captures => { + highlight_closure_captures(sema, token, file_id, span_file_id.file_id()) } + _ if config.references => highlight_references( + sema, + token, + FilePosition { file_id, offset }, + span_file_id.file_id(), + ), _ => None, } } @@ -100,6 +109,7 @@ 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(); @@ -132,7 +142,7 @@ fn highlight_closure_captures( .sources(sema.db) .into_iter() .flat_map(|x| x.to_nav(sema.db)) - .filter(|decl| decl.file_id == file_id) + .filter(|decl| decl.file_id == vfs_file_id) .filter_map(|decl| decl.focus_range) .map(move |range| HighlightedRange { range, category }) .chain(usages) @@ -145,6 +155,7 @@ 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)) = sema.check_for_format_args_template(token.clone(), offset) @@ -152,7 +163,10 @@ fn highlight_references( match resolution.map(Definition::from) { Some(def) => iter::once(def).collect(), None => { - return Some(vec![HighlightedRange { range, category: ReferenceCategory::empty() }]) + return Some(vec![HighlightedRange { + range, + category: ReferenceCategory::empty(), + }]); } } } else { @@ -224,6 +238,23 @@ fn highlight_references( } } + // highlight the tail expr of the labelled block + if matches!(def, Definition::Label(_)) { + let label = token.parent_ancestors().nth(1).and_then(ast::Label::cast); + if let Some(block) = + label.and_then(|label| label.syntax().parent()).and_then(ast::BlockExpr::cast) + { + for_each_tail_expr(&block.into(), &mut |tail| { + if !matches!(tail, ast::Expr::BreakExpr(_)) { + res.insert(HighlightedRange { + range: tail.syntax().text_range(), + category: ReferenceCategory::empty(), + }); + } + }); + } + } + // highlight the defs themselves match def { Definition::Local(local) => { @@ -236,7 +267,7 @@ fn highlight_references( .sources(sema.db) .into_iter() .flat_map(|x| x.to_nav(sema.db)) - .filter(|decl| decl.file_id == file_id) + .filter(|decl| decl.file_id == vfs_file_id) .filter_map(|decl| decl.focus_range) .map(|range| HighlightedRange { range, category }) .for_each(|x| { @@ -254,7 +285,7 @@ fn highlight_references( }, }; for nav in navs { - if nav.file_id != file_id { + if nav.file_id != vfs_file_id { continue; } let hl_range = nav.focus_range.map(|range| { @@ -274,11 +305,7 @@ fn highlight_references( } res.extend(usages); - if res.is_empty() { - None - } else { - Some(res.into_iter().collect()) - } + if res.is_empty() { None } else { Some(res.into_iter().collect()) } } fn hl_exit_points( @@ -442,6 +469,18 @@ pub(crate) fn highlight_break_points( push_to_highlights(file_id, text_range); }); + if matches!(expr, ast::Expr::BlockExpr(_)) { + for_each_tail_expr(&expr, &mut |tail| { + if matches!(tail, ast::Expr::BreakExpr(_)) { + return; + } + + let file_id = sema.hir_file_for(tail.syntax()); + let range = tail.syntax().text_range(); + push_to_highlights(file_id, Some(range)); + }); + } + Some(highlights) } @@ -2068,4 +2107,41 @@ pub unsafe fn bootstrap() -> ! { "#, ) } + + #[test] + fn labeled_block_tail_expr() { + check( + r#" +fn foo() { + 'a: { + // ^^^ + if true { break$0 'a 0; } + // ^^^^^^^^ + 5 + // ^ + } +} +"#, + ); + } + + #[test] + fn labeled_block_tail_expr_2() { + check( + r#" +fn foo() { + let _ = 'b$0lk: { + // ^^^^ + let x = 1; + if true { break 'blk 42; } + // ^^^^ + if false { break 'blk 24; } + // ^^^^ + 100 + // ^^^ + }; +} +"#, + ); + } } |