aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r--crates/ra_analysis/Cargo.toml1
-rw-r--r--crates/ra_analysis/src/db.rs12
-rw-r--r--crates/ra_analysis/src/descriptors/function/imp.rs4
-rw-r--r--crates/ra_analysis/src/descriptors/function/mod.rs13
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs3
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs9
-rw-r--r--crates/ra_analysis/src/imp.rs2
-rw-r--r--crates/ra_analysis/src/lib.rs1
-rw-r--r--crates/ra_analysis/src/loc2id.rs108
9 files changed, 142 insertions, 11 deletions
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"
11fst = "0.3.1" 11fst = "0.3.1"
12salsa = "0.8.0" 12salsa = "0.8.0"
13rustc-hash = "1.0" 13rustc-hash = "1.0"
14parking_lot = "0.6.4"
14ra_syntax = { path = "../ra_syntax" } 15ra_syntax = { path = "../ra_syntax" }
15ra_editor = { path = "../ra_editor" } 16ra_editor = { path = "../ra_editor" }
16test_utils = { path = "../test_utils" } 17test_utils = { path = "../test_utils" }
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index 194f1a6b0..d78b6afb9 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -12,12 +12,14 @@ use crate::{
12 }, 12 },
13 symbol_index::SymbolIndex, 13 symbol_index::SymbolIndex,
14 syntax_ptr::SyntaxPtr, 14 syntax_ptr::SyntaxPtr,
15 loc2id::{IdMaps, IdDatabase},
15 Cancelable, Canceled, FileId, 16 Cancelable, Canceled, FileId,
16}; 17};
17 18
18#[derive(Debug)] 19#[derive(Debug)]
19pub(crate) struct RootDatabase { 20pub(crate) struct RootDatabase {
20 runtime: salsa::Runtime<RootDatabase>, 21 runtime: salsa::Runtime<RootDatabase>,
22 id_maps: IdMaps,
21} 23}
22 24
23impl salsa::Database for RootDatabase { 25impl salsa::Database for RootDatabase {
@@ -29,7 +31,8 @@ impl salsa::Database for RootDatabase {
29impl Default for RootDatabase { 31impl Default for RootDatabase {
30 fn default() -> RootDatabase { 32 fn default() -> RootDatabase {
31 let mut db = RootDatabase { 33 let mut db = RootDatabase {
32 runtime: Default::default(), 34 runtime: salsa::Runtime::default(),
35 id_maps: IdMaps::default(),
33 }; 36 };
34 db.query_mut(crate::input::SourceRootQuery) 37 db.query_mut(crate::input::SourceRootQuery)
35 .set(crate::input::WORKSPACE, Default::default()); 38 .set(crate::input::WORKSPACE, Default::default());
@@ -53,10 +56,17 @@ impl salsa::ParallelDatabase for RootDatabase {
53 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { 56 fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
54 salsa::Snapshot::new(RootDatabase { 57 salsa::Snapshot::new(RootDatabase {
55 runtime: self.runtime.snapshot(self), 58 runtime: self.runtime.snapshot(self),
59 id_maps: self.id_maps.clone(),
56 }) 60 })
57 } 61 }
58} 62}
59 63
64impl IdDatabase for RootDatabase {
65 fn id_maps(&self) -> &IdMaps {
66 &self.id_maps
67 }
68}
69
60salsa::database_storage! { 70salsa::database_storage! {
61 pub(crate) struct RootDatabaseStorage for RootDatabase { 71 pub(crate) struct RootDatabaseStorage for RootDatabase {
62 impl crate::input::FilesDatabase { 72 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::{
8}; 8};
9 9
10/// Resolve `FnId` to the corresponding `SyntaxNode` 10/// Resolve `FnId` to the corresponding `SyntaxNode`
11/// TODO: this should return something more type-safe then `SyntaxNode`
12pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode { 11pub(crate) fn fn_syntax(db: &impl DescriptorDatabase, fn_id: FnId) -> FnDefNode {
13 let syntax = db.resolve_syntax_ptr(fn_id.0); 12 let ptr = db.id_maps().fn_ptr(fn_id);
13 let syntax = db.resolve_syntax_ptr(ptr);
14 FnDef::cast(syntax.borrowed()).unwrap().owned() 14 FnDef::cast(syntax.borrowed()).unwrap().owned()
15} 15}
16 16
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::{
8 TextRange, TextUnit, 8 TextRange, TextUnit,
9}; 9};
10 10
11use crate::{syntax_ptr::SyntaxPtr, FileId}; 11use crate::{
12 syntax_ptr::SyntaxPtr, FileId,
13 loc2id::IdDatabase,
14};
12 15
13pub(crate) use self::scope::{resolve_local_name, FnScopes}; 16pub(crate) use self::scope::{resolve_local_name, FnScopes};
14 17pub(crate) use crate::loc2id::FnId;
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub(crate) struct FnId(SyntaxPtr);
17 18
18impl FnId { 19impl FnId {
19 pub(crate) fn new(file_id: FileId, fn_def: ast::FnDef) -> FnId { 20 pub(crate) fn get(db: &impl IdDatabase, file_id: FileId, fn_def: ast::FnDef) -> FnId {
20 let ptr = SyntaxPtr::new(file_id, fn_def.syntax()); 21 let ptr = SyntaxPtr::new(file_id, fn_def.syntax());
21 FnId(ptr) 22 db.id_maps().fn_id(ptr)
22 } 23 }
23} 24}
24 25
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::{
13 descriptors::function::{resolve_local_name, FnId, FnScopes}, 13 descriptors::function::{resolve_local_name, FnId, FnScopes},
14 descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource}, 14 descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource},
15 input::SourceRootId, 15 input::SourceRootId,
16 loc2id::IdDatabase,
16 syntax_ptr::LocalSyntaxPtr, 17 syntax_ptr::LocalSyntaxPtr,
17 Cancelable, 18 Cancelable,
18}; 19};
19 20
20salsa::query_group! { 21salsa::query_group! {
21 pub(crate) trait DescriptorDatabase: SyntaxDatabase { 22 pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase {
22 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> { 23 fn module_tree(source_root_id: SourceRootId) -> Cancelable<Arc<ModuleTree>> {
23 type ModuleTreeQuery; 24 type ModuleTreeQuery;
24 use fn module::imp::module_tree; 25 use fn module::imp::module_tree;
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 {
58#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] 58#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
59pub(crate) struct ModuleId(u32); 59pub(crate) struct ModuleId(u32);
60 60
61impl crate::loc2id::NumericId for ModuleId {
62 fn from_u32(id: u32) -> Self {
63 ModuleId(id)
64 }
65 fn to_u32(self) -> u32 {
66 self.0
67 }
68}
69
61#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] 70#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
62pub(crate) struct LinkId(u32); 71pub(crate) struct LinkId(u32);
63 72
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(
621 name_ref: ast::NameRef, 621 name_ref: ast::NameRef,
622) -> Option<(SmolStr, TextRange)> { 622) -> Option<(SmolStr, TextRange)> {
623 let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?; 623 let fn_def = name_ref.syntax().ancestors().find_map(ast::FnDef::cast)?;
624 let fn_id = FnId::new(file_id, fn_def); 624 let fn_id = FnId::get(db, file_id, fn_def);
625 let scopes = db.fn_scopes(fn_id); 625 let scopes = db.fn_scopes(fn_id);
626 let scope_entry = crate::descriptors::function::resolve_local_name(name_ref, &scopes)?; 626 let scope_entry = crate::descriptors::function::resolve_local_name(name_ref, &scopes)?;
627 let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id)); 627 let syntax = db.resolve_syntax_ptr(scope_entry.ptr().into_global(file_id));
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;
10extern crate salsa; 10extern crate salsa;
11 11
12mod db; 12mod db;
13mod loc2id;
13mod input; 14mod input;
14mod imp; 15mod imp;
15mod completion; 16mod completion;
diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs
new file mode 100644
index 000000000..8eaa24997
--- /dev/null
+++ b/crates/ra_analysis/src/loc2id.rs
@@ -0,0 +1,108 @@
1use parking_lot::Mutex;
2
3use std::{
4 hash::Hash,
5 sync::Arc,
6};
7
8use rustc_hash::FxHashMap;
9
10use crate::{
11 syntax_ptr::SyntaxPtr,
12};
13
14/// There are two principle ways to refer to things:
15/// - by their locatinon (module in foo/bar/baz.rs at line 42)
16/// - by their numeric id (module `ModuleId(42)`)
17///
18/// The first one is more powerful (you can actually find the thing in question
19/// by id), but the second one is so much more compact.
20///
21/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a
22/// bidirectional mapping between positional and numeric ids, we can use compact
23/// representation wich still allows us to get the actual item
24#[derive(Debug)]
25pub(crate) struct Loc2IdMap<L, ID>
26where
27 ID: NumericId,
28 L: Clone + Eq + Hash,
29{
30 loc2id: FxHashMap<L, ID>,
31 id2loc: FxHashMap<ID, L>,
32}
33
34impl<L, ID> Default for Loc2IdMap<L, ID>
35where
36 ID: NumericId,
37 L: Clone + Eq + Hash,
38{
39 fn default() -> Self {
40 Loc2IdMap {
41 loc2id: FxHashMap::default(),
42 id2loc: FxHashMap::default(),
43 }
44 }
45}
46
47impl<L, ID> Loc2IdMap<L, ID>
48where
49 ID: NumericId,
50 L: Clone + Eq + Hash,
51{
52 pub fn loc2id(&mut self, loc: &L) -> ID {
53 match self.loc2id.get(loc) {
54 Some(id) => return id.clone(),
55 None => (),
56 }
57 let id = self.loc2id.len();
58 assert!(id < u32::max_value() as usize);
59 let id = ID::from_u32(id as u32);
60 self.loc2id.insert(loc.clone(), id.clone());
61 self.id2loc.insert(id.clone(), loc.clone());
62 id
63 }
64
65 pub fn id2loc(&self, id: ID) -> L {
66 self.id2loc[&id].clone()
67 }
68}
69
70pub(crate) trait NumericId: Clone + Eq + Hash {
71 fn from_u32(id: u32) -> Self;
72 fn to_u32(self) -> u32;
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
76pub(crate) struct FnId(u32);
77
78impl NumericId for FnId {
79 fn from_u32(id: u32) -> FnId {
80 FnId(id)
81 }
82 fn to_u32(self) -> u32 {
83 self.0
84 }
85}
86
87pub(crate) trait IdDatabase: salsa::Database {
88 fn id_maps(&self) -> &IdMaps;
89}
90
91#[derive(Debug, Default, Clone)]
92pub(crate) struct IdMaps {
93 inner: Arc<IdMapsInner>,
94}
95
96impl IdMaps {
97 pub(crate) fn fn_id(&self, ptr: SyntaxPtr) -> FnId {
98 self.inner.fns.lock().loc2id(&ptr)
99 }
100 pub(crate) fn fn_ptr(&self, fn_id: FnId) -> SyntaxPtr {
101 self.inner.fns.lock().id2loc(fn_id)
102 }
103}
104
105#[derive(Debug, Default)]
106struct IdMapsInner {
107 fns: Mutex<Loc2IdMap<SyntaxPtr, FnId>>,
108}