From ae6e8d56d44c388b3dff5adbac3585de5553cce9 Mon Sep 17 00:00:00 2001 From: roife Date: Mon, 8 Jul 2024 04:18:32 +0800 Subject: [PATCH] use token_ancestors_with_macros to simplify goto-def on kw --- crates/ide/src/goto_definition.rs | 122 ++++++++++------------------ crates/ide/src/highlight_related.rs | 6 +- 2 files changed, 45 insertions(+), 83 deletions(-) diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 0a4fbc874a..284fd7861d 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs @@ -5,8 +5,7 @@ use crate::{ RangeInfo, TryToNav, UpmappingResult, }; use hir::{ - AsAssocItem, AssocItem, DescendPreference, HirFileId, InFile, MacroFileIdExt, ModuleDef, - Semantics, + AsAssocItem, AssocItem, DescendPreference, InFile, MacroFileIdExt, ModuleDef, Semantics, }; use ide_db::{ base_db::{AnchoredPath, FileLoader}, @@ -15,11 +14,12 @@ use ide_db::{ FileId, RootDatabase, }; use itertools::Itertools; +use span::FileRange; use syntax::{ - ast::{self, HasLoopBody}, + ast::{self, HasLoopBody, Label}, match_ast, AstNode, AstToken, - SyntaxKind::{self, *}, - SyntaxNode, SyntaxToken, TextRange, T, + SyntaxKind::*, + SyntaxToken, TextRange, T, }; // Feature: Go to Definition @@ -224,30 +224,28 @@ fn try_find_fn_or_closure( ) -> Option> { fn find_exit_point( sema: &Semantics<'_, RootDatabase>, - file_id: HirFileId, - ancestors: impl Iterator, - cursor_token_kind: SyntaxKind, + token: SyntaxToken, ) -> Option> { let db = sema.db; - for anc in ancestors { + for anc in sema.token_ancestors_with_macros(token.clone()) { + let file_id = sema.hir_file_for(&anc); match_ast! { match anc { ast::Fn(fn_) => { - let hir_fn: hir::Function = sema.to_def(&fn_)?; - let nav = hir_fn.try_to_nav(db)?; - + let fn_: ast::Fn = fn_; + let nav = sema.to_def(&fn_)?.try_to_nav(db)?; // For async token, we navigate to itself, which triggers // VSCode to find the references - let focus_token = if matches!(cursor_token_kind, T![async]) { + let focus_token = if matches!(token.kind(), T![async]) { fn_.async_token()? } else { fn_.fn_token()? }; - let focus_range = InFile::new(file_id, focus_token.text_range()) - .original_node_file_range_opt(db) - .map(|(frange, _)| frange.range); + let focus_range = InFile::new(file_id, focus_token.text_range()) + .original_node_file_range_opt(db) + .map(|(frange, _)| frange.range); return Some(nav.map(|it| { if focus_range.is_some_and(|range| it.full_range.contains_range(range)) { NavigationTarget { focus_range, ..it } @@ -258,21 +256,26 @@ fn try_find_fn_or_closure( }, ast::ClosureExpr(c) => { let pipe_tok = c.param_list().and_then(|it| it.pipe_token())?.into(); - let nav = NavigationTarget::from_expr(db, InFile::new(file_id, c.into()), pipe_tok); + let c_infile = InFile::new(file_id, c.into()); + let nav = NavigationTarget::from_expr(db, c_infile, pipe_tok); return Some(nav); }, - ast::BlockExpr(blk) => match blk.modifier() { - Some(ast::BlockModifier::Async(_)) => { - let async_tok = blk.async_token()?.into(); - let nav = NavigationTarget::from_expr(db, InFile::new(file_id, blk.into()), async_tok); - return Some(nav); - }, - Some(ast::BlockModifier::Try(_)) if cursor_token_kind != T![return] => { - let try_tok = blk.try_token()?.into(); - let nav = NavigationTarget::from_expr(db, InFile::new(file_id, blk.into()), try_tok); - return Some(nav); - }, - _ => {} + ast::BlockExpr(blk) => { + match blk.modifier() { + Some(ast::BlockModifier::Async(_)) => { + let async_tok = blk.async_token()?.into(); + let blk_infile = InFile::new(file_id, blk.into()); + let nav = NavigationTarget::from_expr(db, blk_infile, async_tok); + return Some(nav); + }, + Some(ast::BlockModifier::Try(_)) if token.kind() != T![return] => { + let try_tok = blk.try_token()?.into(); + let blk_infile = InFile::new(file_id, blk.into()); + let nav = NavigationTarget::from_expr(db, blk_infile, try_tok); + return Some(nav); + }, + _ => {} + } }, _ => {} } @@ -281,28 +284,9 @@ fn try_find_fn_or_closure( None } - let token_kind = token.kind(); sema.descend_into_macros(DescendPreference::None, token.clone()) .into_iter() - .filter_map(|descended| { - let file_id = sema.hir_file_for(&descended.parent()?); - - // Try to find the function in the macro file - find_exit_point(sema, file_id, descended.parent_ancestors(), token_kind).or_else(|| { - // If not found, try to find it in the root file - if file_id.is_macro() { - token - .parent_ancestors() - .find(|it| ast::TokenTree::can_cast(it.kind())) - .and_then(|parent| { - let file_id = sema.hir_file_for(&parent); - find_exit_point(sema, file_id, parent.ancestors(), token_kind) - }) - } else { - None - } - }) - }) + .filter_map(|descended| find_exit_point(sema, descended)) .flatten() .collect_vec() .into() @@ -314,19 +298,13 @@ fn try_find_loop( ) -> Option> { fn find_break_point( sema: &Semantics<'_, RootDatabase>, - file_id: HirFileId, - ancestors: impl Iterator, - lbl: &Option, + token: SyntaxToken, + label_matches: impl Fn(Option