From 5609989368e5cd5137e8860b7a78859b98e89085 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 9 Jan 2019 01:57:40 +0300 Subject: more stable DefIds via bfs tree walking --- crates/ra_hir/src/ids.rs | 21 +++++++++++++++++++-- crates/ra_hir/src/nameres/tests.rs | 17 ++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 3db757778..8ac49eba3 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs @@ -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) -> SourceFileItemId { @@ -305,3 +309,16 @@ impl std::ops::Index 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); + } +} diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index a19a6fe51..17de54b44 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs @@ -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; ", ); } -- cgit v1.2.3