From cb22a799d60c6c5f81ad0f3d0361f575264f3bc2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 18 Nov 2018 15:44:24 +0300 Subject: Add Loc2IdMap --- crates/ra_analysis/Cargo.toml | 1 + crates/ra_analysis/src/db.rs | 8 +++ crates/ra_analysis/src/descriptors/module/mod.rs | 9 ++++ crates/ra_analysis/src/lib.rs | 1 + crates/ra_analysis/src/loc2id.rs | 64 ++++++++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 crates/ra_analysis/src/loc2id.rs (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/Cargo.toml b/crates/ra_analysis/Cargo.toml index 908ee1c81..b4a1a09b5 100644 --- a/crates/ra_analysis/Cargo.toml +++ b/crates/ra_analysis/Cargo.toml @@ -11,6 +11,7 @@ rayon = "1.0.2" fst = "0.3.1" salsa = "0.8.0" rustc-hash = "1.0" +parking_lot = "0.6.4" ra_syntax = { path = "../ra_syntax" } ra_editor = { path = "../ra_editor" } test_utils = { path = "../test_utils" } diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 194f1a6b0..baf6d915a 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs @@ -1,5 +1,7 @@ use std::sync::Arc; +use parking_lot::Mutex; + use ra_editor::LineIndex; use ra_syntax::{SourceFileNode, SyntaxNode}; use salsa::{self, Database}; @@ -9,15 +11,19 @@ use crate::{ descriptors::{ DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, SubmodulesQuery, + module::{ModuleSource, ModuleId}, }, + input::SourceRootId, symbol_index::SymbolIndex, syntax_ptr::SyntaxPtr, + loc2id::Loc2IdMap, Cancelable, Canceled, FileId, }; #[derive(Debug)] pub(crate) struct RootDatabase { runtime: salsa::Runtime, + loc2id: Arc>>, } impl salsa::Database for RootDatabase { @@ -30,6 +36,7 @@ impl Default for RootDatabase { fn default() -> RootDatabase { let mut db = RootDatabase { runtime: Default::default(), + loc2id: Default::default(), }; db.query_mut(crate::input::SourceRootQuery) .set(crate::input::WORKSPACE, Default::default()); @@ -53,6 +60,7 @@ impl salsa::ParallelDatabase for RootDatabase { fn snapshot(&self) -> salsa::Snapshot { salsa::Snapshot::new(RootDatabase { runtime: self.runtime.snapshot(self), + loc2id: Arc::clone(&self.loc2id), }) } } diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index bc1148b22..055a56b54 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs @@ -58,6 +58,15 @@ enum ModuleSourceNode { #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub(crate) struct ModuleId(u32); +impl crate::loc2id::NumericId for ModuleId { + fn from_u32(id: u32) -> Self { + ModuleId(id) + } + fn to_u32(self) -> u32 { + self.0 + } +} + #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub(crate) struct LinkId(u32); diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index ab0e3cb0c..eccda84a7 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs @@ -10,6 +10,7 @@ extern crate rustc_hash; extern crate salsa; mod db; +mod loc2id; mod input; mod imp; mod completion; diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs new file mode 100644 index 000000000..a53ce8348 --- /dev/null +++ b/crates/ra_analysis/src/loc2id.rs @@ -0,0 +1,64 @@ +use std::hash::Hash; + +use rustc_hash::FxHashMap; + +/// There are two principle ways to refer to things: +/// - by their locatinon (module in foo/bar/baz.rs at line 42) +/// - by their numeric id (module `ModuleId(42)`) +/// +/// The first one is more powerful (you can actually find the thing in question +/// by id), but the second one is so much more compact. +/// +/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a +/// bidirectional mapping between positional and numeric ids, we can use compact +/// representation wich still allows us to get the actual item +#[derive(Debug)] +pub(crate) struct Loc2IdMap +where + ID: NumericId, + L: Clone + Eq + Hash, +{ + loc2id: FxHashMap, + id2loc: FxHashMap, +} + +impl Default for Loc2IdMap +where + ID: NumericId, + L: Clone + Eq + Hash, +{ + fn default() -> Self { + Loc2IdMap { + loc2id: FxHashMap::default(), + id2loc: FxHashMap::default(), + } + } +} + +impl Loc2IdMap +where + ID: NumericId, + L: Clone + Eq + Hash, +{ + pub fn loc2id(&mut self, loc: &L) -> ID { + match self.loc2id.get(loc) { + Some(id) => return id.clone(), + None => (), + } + let id = self.loc2id.len(); + assert!(id < u32::max_value() as usize); + let id = ID::from_u32(id as u32); + self.loc2id.insert(loc.clone(), id.clone()); + self.id2loc.insert(id.clone(), loc.clone()); + id + } + + pub fn id2loc(&self, id: &ID) -> L { + self.id2loc[id].clone() + } +} + +pub(crate) trait NumericId: Clone + Eq + Hash { + fn from_u32(id: u32) -> Self; + fn to_u32(self) -> u32; +} -- cgit v1.2.3 From 4e48917c00d24e1e1785e1959a2f3495a902410b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 18 Nov 2018 16:21:23 +0300 Subject: use loc2id for FnIds --- crates/ra_analysis/src/db.rs | 20 +++++---- crates/ra_analysis/src/descriptors/function/imp.rs | 4 +- crates/ra_analysis/src/descriptors/function/mod.rs | 13 +++--- crates/ra_analysis/src/descriptors/mod.rs | 3 +- crates/ra_analysis/src/imp.rs | 2 +- crates/ra_analysis/src/loc2id.rs | 50 ++++++++++++++++++++-- 6 files changed, 70 insertions(+), 22 deletions(-) (limited to 'crates/ra_analysis') diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index baf6d915a..d78b6afb9 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs @@ -1,7 +1,5 @@ use std::sync::Arc; -use parking_lot::Mutex; - use ra_editor::LineIndex; use ra_syntax::{SourceFileNode, SyntaxNode}; use salsa::{self, Database}; @@ -11,19 +9,17 @@ use crate::{ descriptors::{ DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, SubmodulesQuery, - module::{ModuleSource, ModuleId}, }, - input::SourceRootId, symbol_index::SymbolIndex, syntax_ptr::SyntaxPtr, - loc2id::Loc2IdMap, + loc2id::{IdMaps, IdDatabase}, Cancelable, Canceled, FileId, }; #[derive(Debug)] pub(crate) struct RootDatabase { runtime: salsa::Runtime, - loc2id: Arc>>, + id_maps: IdMaps, } impl salsa::Database for RootDatabase { @@ -35,8 +31,8 @@ impl salsa::Database for RootDatabase { impl Default for RootDatabase { fn default() -> RootDatabase { let mut db = RootDatabase { - runtime: Default::default(), - loc2id: Default::default(), + runtime: salsa::Runtime::default(), + id_maps: IdMaps::default(), }; db.query_mut(crate::input::SourceRootQuery) .set(crate::input::WORKSPACE, Default::default()); @@ -60,11 +56,17 @@ impl salsa::ParallelDatabase for RootDatabase { fn snapshot(&self) -> salsa::Snapshot { salsa::Snapshot::new(RootDatabase { runtime: self.runtime.snapshot(self), - loc2id: Arc::clone(&self.loc2id), + id_maps: self.id_maps.clone(), }) } } +impl IdDatabase for RootDatabase { + fn id_maps(&self) -> &IdMaps { + &self.id_maps + } +} + salsa::database_storage! { pub(crate) struct RootDatabaseStorage for RootDatabase { impl crate::input::FilesDatabase { diff --git a/crates/ra_analysis/src/descriptors/function/imp.rs b/crates/ra_analysis/src/descriptors/function/imp.rs index a989a04cd..a7257acf9 100644 --- a/crates/ra_analysis/src/descriptors/function/imp.rs +++ b/crates/ra_analysis/src/descriptors/function/imp.rs @@ -8,9 +8,9 @@ use crate::descriptors::{ }; /// Resolve `FnId` to the corresponding `SyntaxNode` -/// TODO: this should return something more type-safe then `SyntaxNode` pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode { - let syntax = db.resolve_syntax_ptr(fn_id.0); + let ptr = db.id_maps().fn_ptr(fn_id); + let syntax = db.resolve_syntax_ptr(ptr); FnDef::cast(syntax.borrowed()).unwrap().owned() } diff --git a/crates/ra_analysis/src/descriptors/function/mod.rs b/crates/ra_analysis/src/descriptors/function/mod.rs index d5db28a64..86eee5e93 100644 --- a/crates/ra_analysis/src/descriptors/function/mod.rs +++ b/crates/ra_analysis/src/descriptors/function/mod.rs @@ -8,17 +8,18 @@ use ra_syntax::{ TextRange, TextUnit, }; -use crate::{syntax_ptr::SyntaxPtr, FileId}; +use crate::{ + syntax_ptr::SyntaxPtr, FileId, + loc2id::IdDatabase, +}; pub(crate) use self::scope::{resolve_local_name, FnScopes}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub(crate) struct FnId(SyntaxPtr); +pub(crate) use crate::loc2id::FnId; impl FnId { - pub(crate) fn new(file_id: FileId, fn_def: ast::FnDef) -> FnId { + pub(crate) fn get(db: &impl IdDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId { let ptr = SyntaxPtr::new(file_id, fn_def.syntax()); - FnId(ptr) + db.id_maps().fn_id(ptr) } } diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index 56bde3849..d602c4e04 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs @@ -13,12 +13,13 @@ use crate::{ descriptors::function::{resolve_local_name, FnId, FnScopes}, descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource}, input::SourceRootId, + loc2id::IdDatabase, syntax_ptr::LocalSyntaxPtr, Cancelable, }; salsa::query_group! { - pub(crate) trait DescriptorDatabase: SyntaxDatabase { + pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { fn module_tree(source_root_id: SourceRootId) -> Cancelable> { type ModuleTreeQuery; use fn module::imp::module_tree; diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 74c248a96..812fed32d 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -621,7 +621,7 @@ fn resolve_local_name( name_ref: ast::NameRef, ) -> Option<(SmolStr, TextRange)> { let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?; - let fn_id = FnId::new(file_id, fn_def); + let fn_id = FnId::get(db, file_id, fn_def); let scopes = db.fn_scopes(fn_id); let scope_entry = crate::descriptors::function::resolve_local_name(name_ref, &scopes)?; let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id)); diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs index a53ce8348..8eaa24997 100644 --- a/crates/ra_analysis/src/loc2id.rs +++ b/crates/ra_analysis/src/loc2id.rs @@ -1,7 +1,16 @@ -use std::hash::Hash; +use parking_lot::Mutex; + +use std::{ + hash::Hash, + sync::Arc, +}; use rustc_hash::FxHashMap; +use crate::{ + syntax_ptr::SyntaxPtr, +}; + /// There are two principle ways to refer to things: /// - by their locatinon (module in foo/bar/baz.rs at line 42) /// - by their numeric id (module `ModuleId(42)`) @@ -53,8 +62,8 @@ where id } - pub fn id2loc(&self, id: &ID) -> L { - self.id2loc[id].clone() + pub fn id2loc(&self, id: ID) -> L { + self.id2loc[&id].clone() } } @@ -62,3 +71,38 @@ pub(crate) trait NumericId: Clone + Eq + Hash { fn from_u32(id: u32) -> Self; fn to_u32(self) -> u32; } + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct FnId(u32); + +impl NumericId for FnId { + fn from_u32(id: u32) -> FnId { + FnId(id) + } + fn to_u32(self) -> u32 { + self.0 + } +} + +pub(crate) trait IdDatabase: salsa::Database { + fn id_maps(&self) -> &IdMaps; +} + +#[derive(Debug, Default, Clone)] +pub(crate) struct IdMaps { + inner: Arc, +} + +impl IdMaps { + pub(crate) fn fn_id(&self, ptr: SyntaxPtr) -> FnId { + self.inner.fns.lock().loc2id(&ptr) + } + pub(crate) fn fn_ptr(&self, fn_id: FnId) -> SyntaxPtr { + self.inner.fns.lock().id2loc(fn_id) + } +} + +#[derive(Debug, Default)] +struct IdMapsInner { + fns: Mutex>, +} -- cgit v1.2.3