When building an item-tree, keep fewer nodes in memory

This commit is contained in:
Aleksey Kladov 2021-01-16 22:38:22 +03:00
parent 842ed790ea
commit b38414c7f4
3 changed files with 27 additions and 9 deletions

4
Cargo.lock generated
View file

@ -1325,9 +1325,9 @@ checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189"
[[package]] [[package]]
name = "rowan" name = "rowan"
version = "0.10.2" version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5093b337dccf58ace6c6d1fe7e28a0b8229c1e72579ae66bae258fbe53df3e0e" checksum = "d55d358c5fda3d5c4484f71a4808f5eeb39a0aff93bf3acebc680a6d15376f3c"
dependencies = [ dependencies = [
"rustc-hash", "rustc-hash",
"smol_str", "smol_str",

View file

@ -72,10 +72,12 @@ impl AstIdMap {
// get lower ids then children. That is, adding a new child does not // get lower ids then children. That is, adding a new child does not
// change parent's id. This means that, say, adding a new function to a // change parent's id. This means that, say, adding a new function to a
// trait does not change ids of top-level items, which helps caching. // trait does not change ids of top-level items, which helps caching.
bfs(node, |it| { bdfs(node, |it| match ast::Item::cast(it) {
if let Some(module_item) = ast::Item::cast(it) { Some(module_item) => {
res.alloc(module_item.syntax()); res.alloc(module_item.syntax());
true
} }
None => false,
}); });
res res
} }
@ -105,14 +107,30 @@ impl AstIdMap {
} }
} }
/// Walks the subtree in bfs order, calling `f` for each node. /// Walks the subtree in bdfs order, calling `f` for each node. What is bdfs
fn bfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode)) { /// order? It is a mix of breadth-first and depth first orders. Nodes for which
/// `f` returns true are visited breadth-first, all the other nodes are explored
/// depth-first.
///
/// In other words, the size of the bfs queue is bound by the number of "true"
/// nodes.
fn bdfs(node: &SyntaxNode, mut f: impl FnMut(SyntaxNode) -> bool) {
let mut curr_layer = vec![node.clone()]; let mut curr_layer = vec![node.clone()];
let mut next_layer = vec![]; let mut next_layer = vec![];
while !curr_layer.is_empty() { while !curr_layer.is_empty() {
curr_layer.drain(..).for_each(|node| { curr_layer.drain(..).for_each(|node| {
let mut preorder = node.preorder();
while let Some(event) = preorder.next() {
match event {
syntax::WalkEvent::Enter(node) => {
if f(node.clone()) {
next_layer.extend(node.children()); next_layer.extend(node.children());
f(node); preorder.skip_subtree();
}
}
syntax::WalkEvent::Leave(_) => {}
}
}
}); });
std::mem::swap(&mut curr_layer, &mut next_layer); std::mem::swap(&mut curr_layer, &mut next_layer);
} }

View file

@ -12,7 +12,7 @@ doctest = false
[dependencies] [dependencies]
itertools = "0.10.0" itertools = "0.10.0"
rowan = "0.10.1" rowan = "0.10.3"
rustc_lexer = { version = "697.0.0", package = "rustc-ap-rustc_lexer" } rustc_lexer = { version = "697.0.0", package = "rustc-ap-rustc_lexer" }
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
arrayvec = "0.5.1" arrayvec = "0.5.1"