Skip to content

Commit ff90b55

Browse files
committed
Implement ancestors_with_macros in a better way
1 parent c80dc0a commit ff90b55

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

crates/ra_hir/src/source_binder.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ fn def_with_body_from_child_node(
7676
db: &impl HirDatabase,
7777
child: InFile<&SyntaxNode>,
7878
) -> Option<DefWithBody> {
79-
ancestors_with_macros(db, child).find_map(|node| {
79+
child.cloned().ancestors_with_macros(db).find_map(|node| {
8080
let n = &node.value;
8181
match_ast! {
8282
match n {
@@ -89,17 +89,6 @@ fn def_with_body_from_child_node(
8989
})
9090
}
9191

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-
10392
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
10493
/// original source files. It should not be used inside the HIR itself.
10594
#[derive(Debug)]

crates/ra_hir_expand/src/lib.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,40 @@ impl<T> InFile<T> {
301301
db.parse_or_expand(self.file_id).expect("source created from invalid file")
302302
}
303303
}
304+
305+
impl<T: Clone> InFile<&T> {
306+
pub fn cloned(&self) -> InFile<T> {
307+
self.with_value(self.value.clone())
308+
}
309+
}
310+
311+
impl InFile<SyntaxNode> {
312+
pub fn ancestors_with_macros<'a>(
313+
self,
314+
db: &'a impl crate::db::AstDatabase,
315+
) -> impl Iterator<Item = InFile<SyntaxNode>> + 'a {
316+
SyntaxNodeAncestorsWithMacros { db, node: Some(self) }
317+
}
318+
}
319+
320+
pub struct SyntaxNodeAncestorsWithMacros<'a, D: crate::db::AstDatabase> {
321+
db: &'a D,
322+
node: Option<InFile<SyntaxNode>>,
323+
}
324+
325+
impl<'a, D: crate::db::AstDatabase> Iterator for SyntaxNodeAncestorsWithMacros<'a, D> {
326+
type Item = InFile<SyntaxNode>;
327+
fn next(&mut self) -> Option<Self::Item> {
328+
let node = self.node.take()?;
329+
match node.value.parent() {
330+
Some(parent) => {
331+
self.node = Some(node.with_value(parent));
332+
}
333+
None => {
334+
let parent_node = node.file_id.call_node(self.db)?;
335+
self.node = Some(parent_node);
336+
}
337+
}
338+
Some(node)
339+
}
340+
}

0 commit comments

Comments
 (0)