diff options
author | Florian Diebold <[email protected]> | 2019-12-06 18:30:15 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-12-06 20:25:22 +0000 |
commit | a565072ddeac519eea3b415a57e9fd208e20e562 (patch) | |
tree | 4c76dbe6729de22de2f00862b56ed5dfd46d699b /crates/ra_hir/src | |
parent | eae425b10fd7803ae67d2d39e9aca902daa353ba (diff) |
Try to make go to definition work in format!
SourceAnalyzer didn't work properly within expression macro expansions because
it didn't find the enclosing function. Fix this by going up the expansion chain
to find ancestors. This makes the test work, but apparently in real usage it's
still not working.
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 42c392513..cb4345ca1 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -76,18 +76,30 @@ fn def_with_body_from_child_node( | |||
76 | db: &impl HirDatabase, | 76 | db: &impl HirDatabase, |
77 | child: InFile<&SyntaxNode>, | 77 | child: InFile<&SyntaxNode>, |
78 | ) -> Option<DefWithBody> { | 78 | ) -> Option<DefWithBody> { |
79 | child.value.ancestors().find_map(|node| { | 79 | ancestors_with_macros(db, child).find_map(|node| { |
80 | let n = &node.value; | ||
80 | match_ast! { | 81 | match_ast! { |
81 | match node { | 82 | match n { |
82 | ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, | 83 | ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); }, |
83 | ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, | 84 | ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); }, |
84 | ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); }, | 85 | ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); }, |
85 | _ => { None }, | 86 | _ => { None }, |
86 | } | 87 | } |
87 | } | 88 | } |
88 | }) | 89 | }) |
89 | } | 90 | } |
90 | 91 | ||
92 | fn ancestors_with_macros<'a>( | ||
93 | db: &'a (impl HirDatabase), | ||
94 | node: InFile<&SyntaxNode>, | ||
95 | ) -> impl Iterator<Item = InFile<SyntaxNode>> + 'a { | ||
96 | let file = node.with_value(()); // keep just the file id for borrow checker purposes | ||
97 | let parent_node = node.file_id.call_node(db); | ||
98 | let parent_ancestors: Box<dyn Iterator<Item = InFile<SyntaxNode>>> = | ||
99 | Box::new(parent_node.into_iter().flat_map(move |n| ancestors_with_macros(db, n.as_ref()))); | ||
100 | node.value.ancestors().map(move |n| file.with_value(n)).chain(parent_ancestors) | ||
101 | } | ||
102 | |||
91 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of | 103 | /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of |
92 | /// original source files. It should not be used inside the HIR itself. | 104 | /// original source files. It should not be used inside the HIR itself. |
93 | #[derive(Debug)] | 105 | #[derive(Debug)] |
@@ -135,6 +147,7 @@ pub struct ReferenceDescriptor { | |||
135 | pub name: String, | 147 | pub name: String, |
136 | } | 148 | } |
137 | 149 | ||
150 | #[derive(Debug)] | ||
138 | pub struct Expansion { | 151 | pub struct Expansion { |
139 | macro_file_kind: MacroFileKind, | 152 | macro_file_kind: MacroFileKind, |
140 | macro_call_id: MacroCallId, | 153 | macro_call_id: MacroCallId, |