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) { 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) { if let Some(module_item) = ast::ModuleItem::cast(it) {
self.alloc(module_item.syntax().to_owned()); self.alloc(module_item.syntax().to_owned());
} else if let Some(macro_call) = ast::MacroCall::cast(it) { } else if let Some(macro_call) = ast::MacroCall::cast(it) {
self.alloc(macro_call.syntax().to_owned()); self.alloc(macro_call.syntax().to_owned());
} }
}); })
} }
fn alloc(&mut self, item: TreePtr<SyntaxNode>) -> SourceFileItemId { fn alloc(&mut self, item: TreePtr<SyntaxNode>) -> SourceFileItemId {
@ -305,3 +309,16 @@ impl std::ops::Index<SourceFileItemId> for SourceFileItems {
&self.arena[idx] &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; mod foo;
use crate::foo::bar::Baz; use crate::foo::bar::Baz;
{
fn foo() -> i32 { 92 } fn foo() -> i32 { 92 }
", ",
); );
@ -380,12 +380,15 @@ fn adding_inner_items_should_not_invalidate_item_map() {
" "
//- /lib.rs //- /lib.rs
struct S { a: i32} struct S { a: i32}
mod foo;<|>
enum E { A } enum E { A }
use crate::foo::bar::Baz;
trait T { trait T {
fn a() {} fn a() {}
} }
mod foo;<|>
impl S {
fn a() {}
}
use crate::foo::bar::Baz;
//- /foo/mod.rs //- /foo/mod.rs
pub mod bar; pub mod bar;
@ -394,13 +397,17 @@ fn adding_inner_items_should_not_invalidate_item_map() {
", ",
" "
struct S { a: i32, b: () } struct S { a: i32, b: () }
mod foo;<|>
enum E { A, B } enum E { A, B }
use crate::foo::bar::Baz;
trait T { trait T {
fn a() {} fn a() {}
fn b() {} fn b() {}
} }
mod foo;<|>
impl S {
fn a() {}
fn b() {}
}
use crate::foo::bar::Baz;
", ",
); );
} }