diff options
author | Aleksey Kladov <[email protected]> | 2018-11-18 12:44:24 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-11-18 12:44:24 +0000 |
commit | cb22a799d60c6c5f81ad0f3d0361f575264f3bc2 (patch) | |
tree | 738b06fae809d32f76776d27c71fa869f5dd2544 /crates/ra_analysis | |
parent | f1d8558cd5fe20a351496c39dbb8e15aa028803c (diff) |
Add Loc2IdMap
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r-- | crates/ra_analysis/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_analysis/src/db.rs | 8 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 9 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_analysis/src/loc2id.rs | 64 |
5 files changed, 83 insertions, 0 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" | |||
11 | fst = "0.3.1" | 11 | fst = "0.3.1" |
12 | salsa = "0.8.0" | 12 | salsa = "0.8.0" |
13 | rustc-hash = "1.0" | 13 | rustc-hash = "1.0" |
14 | parking_lot = "0.6.4" | ||
14 | ra_syntax = { path = "../ra_syntax" } | 15 | ra_syntax = { path = "../ra_syntax" } |
15 | ra_editor = { path = "../ra_editor" } | 16 | ra_editor = { path = "../ra_editor" } |
16 | test_utils = { path = "../test_utils" } | 17 | 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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use parking_lot::Mutex; | ||
4 | |||
3 | use ra_editor::LineIndex; | 5 | use ra_editor::LineIndex; |
4 | use ra_syntax::{SourceFileNode, SyntaxNode}; | 6 | use ra_syntax::{SourceFileNode, SyntaxNode}; |
5 | use salsa::{self, Database}; | 7 | use salsa::{self, Database}; |
@@ -9,15 +11,19 @@ use crate::{ | |||
9 | descriptors::{ | 11 | descriptors::{ |
10 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, | 12 | DescriptorDatabase, FnScopesQuery, FnSyntaxQuery, ModuleScopeQuery, ModuleTreeQuery, |
11 | SubmodulesQuery, | 13 | SubmodulesQuery, |
14 | module::{ModuleSource, ModuleId}, | ||
12 | }, | 15 | }, |
16 | input::SourceRootId, | ||
13 | symbol_index::SymbolIndex, | 17 | symbol_index::SymbolIndex, |
14 | syntax_ptr::SyntaxPtr, | 18 | syntax_ptr::SyntaxPtr, |
19 | loc2id::Loc2IdMap, | ||
15 | Cancelable, Canceled, FileId, | 20 | Cancelable, Canceled, FileId, |
16 | }; | 21 | }; |
17 | 22 | ||
18 | #[derive(Debug)] | 23 | #[derive(Debug)] |
19 | pub(crate) struct RootDatabase { | 24 | pub(crate) struct RootDatabase { |
20 | runtime: salsa::Runtime<RootDatabase>, | 25 | runtime: salsa::Runtime<RootDatabase>, |
26 | loc2id: Arc<Mutex<Loc2IdMap<(SourceRootId, ModuleSource), ModuleId>>>, | ||
21 | } | 27 | } |
22 | 28 | ||
23 | impl salsa::Database for RootDatabase { | 29 | impl salsa::Database for RootDatabase { |
@@ -30,6 +36,7 @@ impl Default for RootDatabase { | |||
30 | fn default() -> RootDatabase { | 36 | fn default() -> RootDatabase { |
31 | let mut db = RootDatabase { | 37 | let mut db = RootDatabase { |
32 | runtime: Default::default(), | 38 | runtime: Default::default(), |
39 | loc2id: Default::default(), | ||
33 | }; | 40 | }; |
34 | db.query_mut(crate::input::SourceRootQuery) | 41 | db.query_mut(crate::input::SourceRootQuery) |
35 | .set(crate::input::WORKSPACE, Default::default()); | 42 | .set(crate::input::WORKSPACE, Default::default()); |
@@ -53,6 +60,7 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
53 | fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { | 60 | fn snapshot(&self) -> salsa::Snapshot<RootDatabase> { |
54 | salsa::Snapshot::new(RootDatabase { | 61 | salsa::Snapshot::new(RootDatabase { |
55 | runtime: self.runtime.snapshot(self), | 62 | runtime: self.runtime.snapshot(self), |
63 | loc2id: Arc::clone(&self.loc2id), | ||
56 | }) | 64 | }) |
57 | } | 65 | } |
58 | } | 66 | } |
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)] |
59 | pub(crate) struct ModuleId(u32); | 59 | pub(crate) struct ModuleId(u32); |
60 | 60 | ||
61 | impl 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)] |
62 | pub(crate) struct LinkId(u32); | 71 | pub(crate) struct LinkId(u32); |
63 | 72 | ||
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; | |||
10 | extern crate salsa; | 10 | extern crate salsa; |
11 | 11 | ||
12 | mod db; | 12 | mod db; |
13 | mod loc2id; | ||
13 | mod input; | 14 | mod input; |
14 | mod imp; | 15 | mod imp; |
15 | mod completion; | 16 | 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 @@ | |||
1 | use std::hash::Hash; | ||
2 | |||
3 | use rustc_hash::FxHashMap; | ||
4 | |||
5 | /// There are two principle ways to refer to things: | ||
6 | /// - by their locatinon (module in foo/bar/baz.rs at line 42) | ||
7 | /// - by their numeric id (module `ModuleId(42)`) | ||
8 | /// | ||
9 | /// The first one is more powerful (you can actually find the thing in question | ||
10 | /// by id), but the second one is so much more compact. | ||
11 | /// | ||
12 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a | ||
13 | /// bidirectional mapping between positional and numeric ids, we can use compact | ||
14 | /// representation wich still allows us to get the actual item | ||
15 | #[derive(Debug)] | ||
16 | pub(crate) struct Loc2IdMap<L, ID> | ||
17 | where | ||
18 | ID: NumericId, | ||
19 | L: Clone + Eq + Hash, | ||
20 | { | ||
21 | loc2id: FxHashMap<L, ID>, | ||
22 | id2loc: FxHashMap<ID, L>, | ||
23 | } | ||
24 | |||
25 | impl<L, ID> Default for Loc2IdMap<L, ID> | ||
26 | where | ||
27 | ID: NumericId, | ||
28 | L: Clone + Eq + Hash, | ||
29 | { | ||
30 | fn default() -> Self { | ||
31 | Loc2IdMap { | ||
32 | loc2id: FxHashMap::default(), | ||
33 | id2loc: FxHashMap::default(), | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl<L, ID> Loc2IdMap<L, ID> | ||
39 | where | ||
40 | ID: NumericId, | ||
41 | L: Clone + Eq + Hash, | ||
42 | { | ||
43 | pub fn loc2id(&mut self, loc: &L) -> ID { | ||
44 | match self.loc2id.get(loc) { | ||
45 | Some(id) => return id.clone(), | ||
46 | None => (), | ||
47 | } | ||
48 | let id = self.loc2id.len(); | ||
49 | assert!(id < u32::max_value() as usize); | ||
50 | let id = ID::from_u32(id as u32); | ||
51 | self.loc2id.insert(loc.clone(), id.clone()); | ||
52 | self.id2loc.insert(id.clone(), loc.clone()); | ||
53 | id | ||
54 | } | ||
55 | |||
56 | pub fn id2loc(&self, id: &ID) -> L { | ||
57 | self.id2loc[id].clone() | ||
58 | } | ||
59 | } | ||
60 | |||
61 | pub(crate) trait NumericId: Clone + Eq + Hash { | ||
62 | fn from_u32(id: u32) -> Self; | ||
63 | fn to_u32(self) -> u32; | ||
64 | } | ||