aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/loc2id.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/loc2id.rs')
-rw-r--r--crates/ra_analysis/src/loc2id.rs108
1 files changed, 108 insertions, 0 deletions
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}