aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-06 18:30:15 +0000
committerFlorian Diebold <[email protected]>2019-12-06 20:25:22 +0000
commita565072ddeac519eea3b415a57e9fd208e20e562 (patch)
tree4c76dbe6729de22de2f00862b56ed5dfd46d699b /crates/ra_hir/src
parenteae425b10fd7803ae67d2d39e9aca902daa353ba (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.rs23
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
92fn 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)]
138pub struct Expansion { 151pub struct Expansion {
139 macro_file_kind: MacroFileKind, 152 macro_file_kind: MacroFileKind,
140 macro_call_id: MacroCallId, 153 macro_call_id: MacroCallId,