more stable DefIds via bfs tree walking

This commit is contained in:
Aleksey Kladov 2019-01-09 01:57:40 +03:00
parent 2dc85619be
commit 5609989368
2 changed files with 31 additions and 7 deletions

View File

@ -253,13 +253,17 @@ impl SourceFileItems {
}
fn init(&mut self, source_file: &SourceFile) {
source_file.syntax().descendants().for_each(|it| {
// By walking the tree in bread-first order we make sure that parents
// get lower ids then children. That is, addding a new child does not
// change parent's id. This means that, say, adding a new function to a
// trait does not chage ids of top-level items, which helps caching.
bfs(source_file.syntax(), |it| {
if let Some(module_item) = ast::ModuleItem::cast(it) {
self.alloc(module_item.syntax().to_owned());
} else if let Some(macro_call) = ast::MacroCall::cast(it) {
self.alloc(macro_call.syntax().to_owned());
}
});
})
}
fn alloc(&mut self, item: TreePtr<SyntaxNode>) -> SourceFileItemId {
@ -305,3 +309,16 @@ impl std::ops::Index<SourceFileItemId> for SourceFileItems {
&self.arena[idx]
}
}
/// Walks the subtree in bfs order, calling `f` for each node.
fn bfs(node: &SyntaxNode, mut f: impl FnMut(&SyntaxNode)) {
let mut curr_layer = vec![node];
let mut next_layer = vec![];
while !curr_layer.is_empty() {
curr_layer.drain(..).for_each(|node| {
next_layer.extend(node.children());
f(node);
});
std::mem::swap(&mut curr_layer, &mut next_layer);
}
}

View File

@ -368,7 +368,7 @@ fn typing_inside_a_function_should_not_invalidate_item_map() {
mod foo;
use crate::foo::bar::Baz;
{
fn foo() -> i32 { 92 }
",
);
@ -380,12 +380,15 @@ fn adding_inner_items_should_not_invalidate_item_map() {
"
//- /lib.rs
struct S { a: i32}
mod foo;<|>
enum E { A }
use crate::foo::bar::Baz;
trait T {
fn a() {}
}
mod foo;<|>
impl S {
fn a() {}
}
use crate::foo::bar::Baz;
//- /foo/mod.rs
pub mod bar;
@ -394,13 +397,17 @@ fn adding_inner_items_should_not_invalidate_item_map() {
",
"
struct S { a: i32, b: () }
mod foo;<|>
enum E { A, B }
use crate::foo::bar::Baz;
trait T {
fn a() {}
fn b() {}
}
mod foo;<|>
impl S {
fn a() {}
fn b() {}
}
use crate::foo::bar::Baz;
",
);
}