|
1 | 1 | use ide_db::{base_db::Upcast, helpers::pick_best_token, RootDatabase};
|
2 |
| -use rustc_hash::FxHashSet; |
3 | 2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, T};
|
4 | 3 |
|
5 | 4 | use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo};
|
@@ -55,19 +54,29 @@ pub(crate) fn goto_type_definition(
|
55 | 54 | Some((ty, node))
|
56 | 55 | })?;
|
57 | 56 |
|
58 |
| - let mut res = FxHashSet::default(); |
59 |
| - let mut workload = vec![ty.strip_references()]; |
60 |
| - while let Some(ty) = workload.pop() { |
61 |
| - if let Some(adt) = ty.as_adt() { |
62 |
| - res.insert(adt); |
| 57 | + let mut res = Vec::new(); |
| 58 | + let mut push = |def: hir::ModuleDef| { |
| 59 | + if let Some(nav) = def.try_to_nav(db) { |
| 60 | + if !res.contains(&nav) { |
| 61 | + res.push(nav); |
| 62 | + } |
63 | 63 | }
|
64 |
| - workload.extend(ty.strip_references().type_arguments()); |
65 |
| - } |
| 64 | + }; |
| 65 | + |
| 66 | + let ty = ty.strip_references(); |
| 67 | + ty.walk(db, |t| { |
| 68 | + if let Some(adt) = t.as_adt() { |
| 69 | + push(adt.into()); |
| 70 | + } else if let Some(trait_) = t.as_dyn_trait() { |
| 71 | + push(trait_.into()); |
| 72 | + } else if let Some(traits) = t.as_impl_traits(db) { |
| 73 | + traits.into_iter().for_each(|it| push(it.into())); |
| 74 | + } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { |
| 75 | + push(trait_.into()); |
| 76 | + } |
| 77 | + }); |
66 | 78 |
|
67 |
| - Some(RangeInfo::new( |
68 |
| - node.text_range(), |
69 |
| - res.into_iter().flat_map(|adt| adt.try_to_nav(db)).collect(), |
70 |
| - )) |
| 79 | + Some(RangeInfo::new(node.text_range(), res)) |
71 | 80 | }
|
72 | 81 |
|
73 | 82 | #[cfg(test)]
|
|
0 commit comments