@@ -5,8 +5,7 @@ use crate::{
55 RangeInfo, TryToNav, UpmappingResult,
66};
77use hir::{
8- AsAssocItem, AssocItem, DescendPreference, HirFileId, InFile, MacroFileIdExt, ModuleDef,
9- Semantics,
8+ AsAssocItem, AssocItem, DescendPreference, InFile, MacroFileIdExt, ModuleDef, Semantics,
109};
1110use ide_db::{
1211 base_db::{AnchoredPath, FileLoader},
@@ -15,11 +14,12 @@ use ide_db::{
1514 FileId, RootDatabase,
1615};
1716use itertools::Itertools;
17+ use span::FileRange;
1818use syntax::{
19- ast::{self, HasLoopBody},
19+ ast::{self, HasLoopBody, Label },
2020 match_ast, AstNode, AstToken,
21- SyntaxKind::{self, *} ,
22- SyntaxNode, SyntaxToken, TextRange, T,
21+ SyntaxKind::* ,
22+ SyntaxToken, TextRange, T,
2323};
2424
2525// Feature: Go to Definition
@@ -224,30 +224,28 @@ fn try_find_fn_or_closure(
224224) -> Option<Vec<NavigationTarget>> {
225225 fn find_exit_point(
226226 sema: &Semantics<'_, RootDatabase>,
227- file_id: HirFileId,
228- ancestors: impl Iterator<Item = SyntaxNode>,
229- cursor_token_kind: SyntaxKind,
227+ token: SyntaxToken,
230228 ) -> Option<UpmappingResult<NavigationTarget>> {
231229 let db = sema.db;
232230
233- for anc in ancestors {
231+ for anc in sema.token_ancestors_with_macros(token.clone()) {
232+ let file_id = sema.hir_file_for(&anc);
234233 match_ast! {
235234 match anc {
236235 ast::Fn(fn_) => {
237- let hir_fn: hir::Function = sema.to_def(&fn_)?;
238- let nav = hir_fn.try_to_nav(db)?;
239-
236+ let fn_: ast::Fn = fn_;
237+ let nav = sema.to_def(&fn_)?.try_to_nav(db)?;
240238 // For async token, we navigate to itself, which triggers
241239 // VSCode to find the references
242- let focus_token = if matches!(cursor_token_kind , T![async]) {
240+ let focus_token = if matches!(token.kind() , T![async]) {
243241 fn_.async_token()?
244242 } else {
245243 fn_.fn_token()?
246244 };
247- let focus_range = InFile::new(file_id, focus_token.text_range())
248- .original_node_file_range_opt(db)
249- .map(|(frange, _)| frange.range);
250245
246+ let focus_range = InFile::new(file_id, focus_token.text_range())
247+ .original_node_file_range_opt(db)
248+ .map(|(frange, _)| frange.range);
251249 return Some(nav.map(|it| {
252250 if focus_range.is_some_and(|range| it.full_range.contains_range(range)) {
253251 NavigationTarget { focus_range, ..it }
@@ -258,21 +256,26 @@ fn try_find_fn_or_closure(
258256 },
259257 ast::ClosureExpr(c) => {
260258 let pipe_tok = c.param_list().and_then(|it| it.pipe_token())?.into();
261- let nav = NavigationTarget::from_expr(db, InFile::new(file_id, c.into()), pipe_tok);
259+ let c_infile = InFile::new(file_id, c.into());
260+ let nav = NavigationTarget::from_expr(db, c_infile, pipe_tok);
262261 return Some(nav);
263262 },
264- ast::BlockExpr(blk) => match blk.modifier() {
265- Some(ast::BlockModifier::Async(_)) => {
266- let async_tok = blk.async_token()?.into();
267- let nav = NavigationTarget::from_expr(db, InFile::new(file_id, blk.into()), async_tok);
268- return Some(nav);
269- },
270- Some(ast::BlockModifier::Try(_)) if cursor_token_kind != T![return] => {
271- let try_tok = blk.try_token()?.into();
272- let nav = NavigationTarget::from_expr(db, InFile::new(file_id, blk.into()), try_tok);
273- return Some(nav);
274- },
275- _ => {}
263+ ast::BlockExpr(blk) => {
264+ match blk.modifier() {
265+ Some(ast::BlockModifier::Async(_)) => {
266+ let async_tok = blk.async_token()?.into();
267+ let blk_infile = InFile::new(file_id, blk.into());
268+ let nav = NavigationTarget::from_expr(db, blk_infile, async_tok);
269+ return Some(nav);
270+ },
271+ Some(ast::BlockModifier::Try(_)) if token.kind() != T![return] => {
272+ let try_tok = blk.try_token()?.into();
273+ let blk_infile = InFile::new(file_id, blk.into());
274+ let nav = NavigationTarget::from_expr(db, blk_infile, try_tok);
275+ return Some(nav);
276+ },
277+ _ => {}
278+ }
276279 },
277280 _ => {}
278281 }
@@ -281,28 +284,9 @@ fn try_find_fn_or_closure(
281284 None
282285 }
283286
284- let token_kind = token.kind();
285287 sema.descend_into_macros(DescendPreference::None, token.clone())
286288 .into_iter()
287- .filter_map(|descended| {
288- let file_id = sema.hir_file_for(&descended.parent()?);
289-
290- // Try to find the function in the macro file
291- find_exit_point(sema, file_id, descended.parent_ancestors(), token_kind).or_else(|| {
292- // If not found, try to find it in the root file
293- if file_id.is_macro() {
294- token
295- .parent_ancestors()
296- .find(|it| ast::TokenTree::can_cast(it.kind()))
297- .and_then(|parent| {
298- let file_id = sema.hir_file_for(&parent);
299- find_exit_point(sema, file_id, parent.ancestors(), token_kind)
300- })
301- } else {
302- None
303- }
304- })
305- })
289+ .filter_map(|descended| find_exit_point(sema, descended))
306290 .flatten()
307291 .collect_vec()
308292 .into()
@@ -314,19 +298,13 @@ fn try_find_loop(
314298) -> Option<Vec<NavigationTarget>> {
315299 fn find_break_point(
316300 sema: &Semantics<'_, RootDatabase>,
317- file_id: HirFileId,
318- ancestors: impl Iterator<Item = SyntaxNode>,
319- lbl: &Option<ast::Lifetime>,
301+ token: SyntaxToken,
302+ label_matches: impl Fn(Option<Label>) -> bool,
320303 ) -> Option<UpmappingResult<NavigationTarget>> {
321304 let db = sema.db;
322- let label_matches = |it: Option<ast::Label>| match lbl {
323- Some(lbl) => {
324- Some(lbl.text()) == it.and_then(|it| it.lifetime()).as_ref().map(|it| it.text())
325- }
326- None => true,
327- };
305+ let file_id = sema.hir_file_for(&token.parent()?);
328306
329- for anc in ancestors .filter_map(ast::Expr::cast) {
307+ for anc in sema.token_ancestors_with_macros(token.clone()) .filter_map(ast::Expr::cast) {
330308 match anc {
331309 ast::Expr::LoopExpr(loop_) if label_matches(loop_.label()) => {
332310 let expr = ast::Expr::LoopExpr(loop_.clone());
@@ -369,28 +347,16 @@ fn try_find_loop(
369347 _ => None,
370348 }
371349 };
350+ let label_matches =
351+ |it: Option<ast::Label>| match (lbl.as_ref(), it.and_then(|it| it.lifetime())) {
352+ (Some(lbl), Some(it)) => lbl.text() == it.text(),
353+ (None, _) => true,
354+ (Some(_), None) => false,
355+ };
372356
373357 sema.descend_into_macros(DescendPreference::None, token.clone())
374358 .into_iter()
375- .filter_map(|descended| {
376- let file_id = sema.hir_file_for(&descended.parent()?);
377-
378- // Try to find the function in the macro file
379- find_break_point(sema, file_id, descended.parent_ancestors(), &lbl).or_else(|| {
380- // If not found, try to find it in the root file
381- if file_id.is_macro() {
382- token
383- .parent_ancestors()
384- .find(|it| ast::TokenTree::can_cast(it.kind()))
385- .and_then(|parent| {
386- let file_id = sema.hir_file_for(&parent);
387- find_break_point(sema, file_id, parent.ancestors(), &lbl)
388- })
389- } else {
390- None
391- }
392- })
393- })
359+ .filter_map(|descended| find_break_point(sema, descended, label_matches))
394360 .flatten()
395361 .collect_vec()
396362 .into()
0 commit comments