From a565072ddeac519eea3b415a57e9fd208e20e562 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 19:30:15 +0100 Subject: 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. --- crates/ra_hir/src/source_binder.rs | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'crates/ra_hir/src') 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( db: &impl HirDatabase, child: InFile<&SyntaxNode>, ) -> Option { - child.value.ancestors().find_map(|node| { + ancestors_with_macros(db, child).find_map(|node| { + let n = &node.value; match_ast! { - match node { - ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); }, + match n { + ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); }, + ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); }, + ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); }, _ => { None }, } } }) } +fn ancestors_with_macros<'a>( + db: &'a (impl HirDatabase), + node: InFile<&SyntaxNode>, +) -> impl Iterator> + 'a { + let file = node.with_value(()); // keep just the file id for borrow checker purposes + let parent_node = node.file_id.call_node(db); + let parent_ancestors: Box>> = + Box::new(parent_node.into_iter().flat_map(move |n| ancestors_with_macros(db, n.as_ref()))); + node.value.ancestors().map(move |n| file.with_value(n)).chain(parent_ancestors) +} + /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] @@ -135,6 +147,7 @@ pub struct ReferenceDescriptor { pub name: String, } +#[derive(Debug)] pub struct Expansion { macro_file_kind: MacroFileKind, macro_call_id: MacroCallId, -- cgit v1.2.3