aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis')
-rw-r--r--crates/libanalysis/src/db.rs116
-rw-r--r--crates/libanalysis/src/lib.rs2
-rw-r--r--crates/libanalysis/src/module_map_db.rs24
3 files changed, 111 insertions, 31 deletions
diff --git a/crates/libanalysis/src/db.rs b/crates/libanalysis/src/db.rs
index 5e3c8fb7a..31c73c402 100644
--- a/crates/libanalysis/src/db.rs
+++ b/crates/libanalysis/src/db.rs
@@ -2,50 +2,95 @@ use std::{
2 hash::Hash, 2 hash::Hash,
3 sync::Arc, 3 sync::Arc,
4 cell::RefCell, 4 cell::RefCell,
5 fmt::Debug,
5}; 6};
7use parking_lot::Mutex;
6use libsyntax2::{File}; 8use libsyntax2::{File};
7use im; 9use im;
8use { 10use {
9 FileId, 11 FileId,
10 imp::{FileResolverImp}, 12 imp::{FileResolverImp},
13 module_map_db::ModuleDescr,
11}; 14};
12 15
13#[derive(Clone)] 16#[derive(Debug)]
14pub(crate) struct Db { 17pub(crate) struct DbHost {
15 file_resolver: FileResolverImp, 18 db: Arc<Db>,
16 files: im::HashMap<FileId, Arc<String>>,
17} 19}
18 20
19impl Db { 21impl DbHost {
20 pub(crate) fn new() -> Db { 22 pub(crate) fn new() -> DbHost {
21 Db { 23 let db = Db {
22 file_resolver: FileResolverImp::default(), 24 file_resolver: FileResolverImp::default(),
23 files: im::HashMap::new(), 25 files: im::HashMap::new(),
24 } 26 cache: Mutex::new(Cache::new())
27 };
28 DbHost { db: Arc::new(db) }
25 } 29 }
26 pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) { 30 pub(crate) fn change_file(&mut self, file_id: FileId, text: Option<String>) {
31 let db = self.db_mut();
27 match text { 32 match text {
28 None => { 33 None => {
29 self.files.remove(&file_id); 34 db.files.remove(&file_id);
30 } 35 }
31 Some(text) => { 36 Some(text) => {
32 self.files.insert(file_id, Arc::new(text)); 37 db.files.insert(file_id, Arc::new(text));
33 } 38 }
34 } 39 }
35 } 40 }
36 pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) { 41 pub(crate) fn set_file_resolver(&mut self, file_resolver: FileResolverImp) {
37 self.file_resolver = file_resolver 42 let db = self.db_mut();
43 db.file_resolver = file_resolver
38 } 44 }
39 pub(crate) fn query_ctx(&self) -> QueryCtx { 45 pub(crate) fn query_ctx(&self) -> QueryCtx {
40 QueryCtx { 46 QueryCtx {
41 db: self.clone(), 47 db: Arc::clone(&self.db),
42 trace: RefCell::new(Vec::new()), 48 trace: RefCell::new(Vec::new()),
43 } 49 }
44 } 50 }
51 fn db_mut(&mut self) -> &mut Db {
52 // NB: this "forks" the database & clears the cache
53 let db = Arc::make_mut(&mut self.db);
54 *db.cache.get_mut() = Default::default();
55 db
56 }
57}
58
59#[derive(Debug)]
60pub(crate) struct Db {
61 file_resolver: FileResolverImp,
62 files: im::HashMap<FileId, Arc<String>>,
63 cache: Mutex<Cache>,
64}
65
66impl Clone for Db {
67 fn clone(&self) -> Db {
68 Db {
69 file_resolver: self.file_resolver.clone(),
70 files: self.files.clone(),
71 cache: Mutex::new(Cache::new()),
72 }
73 }
74}
75
76#[derive(Clone, Default, Debug)]
77pub(crate) struct Cache {
78 pub(crate) module_descr: QueryCache<ModuleDescr>
79}
80#[allow(type_alias_bounds)]
81pub(crate) type QueryCache<Q: Query> = im::HashMap<
82 <Q as Query>::Params,
83 <Q as Query>::Output
84>;
85
86impl Cache {
87 fn new() -> Cache {
88 Default::default()
89 }
45} 90}
46 91
47pub(crate) struct QueryCtx { 92pub(crate) struct QueryCtx {
48 db: Db, 93 db: Arc<Db>,
49 pub(crate) trace: RefCell<Vec<TraceEvent>>, 94 pub(crate) trace: RefCell<Vec<TraceEvent>>,
50} 95}
51 96
@@ -62,9 +107,7 @@ pub(crate) enum TraceEventKind {
62 107
63impl QueryCtx { 108impl QueryCtx {
64 pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output { 109 pub(crate) fn get<Q: Get>(&self, params: &Q::Params) -> Q::Output {
65 self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Start });
66 let res = Q::get(self, params); 110 let res = Q::get(self, params);
67 self.trace(TraceEvent { query_id: Q::ID, kind: TraceEventKind::Finish });
68 res 111 res
69 } 112 }
70 fn trace(&self, event: TraceEvent) { 113 fn trace(&self, event: TraceEvent) {
@@ -74,26 +117,55 @@ impl QueryCtx {
74 117
75pub(crate) trait Query { 118pub(crate) trait Query {
76 const ID: u32; 119 const ID: u32;
77 type Params: Hash; 120 type Params: Hash + Eq + Debug;
78 type Output; 121 type Output: Debug;
79} 122}
80 123
81pub(crate) trait Get: Query { 124pub(crate) trait Get: Query {
82 fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output; 125 fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
83} 126}
84 127
85impl<T: Eval> Get for T { 128impl<T: Eval> Get for T
129where
130 T::Params: Clone,
131 T::Output: Clone,
132{
86 fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output { 133 fn get(ctx: &QueryCtx, params: &Self::Params) -> Self::Output {
87 Self::eval(ctx, params) 134 {
135 let mut cache = ctx.db.cache.lock();
136 if let Some(cache) = Self::cache(&mut cache) {
137 if let Some(res) = cache.get(params) {
138 return res.clone();
139 }
140 }
141 }
142 ctx.trace(TraceEvent { query_id: Self::ID, kind: TraceEventKind::Start });
143 let res = Self::eval(ctx, params);
144 ctx.trace(TraceEvent { query_id: Self::ID, kind: TraceEventKind::Finish });
145
146 let mut cache = ctx.db.cache.lock();
147 if let Some(cache) = Self::cache(&mut cache) {
148 cache.insert(params.clone(), res.clone());
149 }
150
151 res
88 } 152 }
89} 153}
90 154
91pub(crate) trait Eval: Query { 155pub(crate) trait Eval: Query
156where
157 Self::Params: Clone,
158 Self::Output: Clone,
159 {
160 fn cache(_cache: &mut Cache) -> Option<&mut QueryCache<Self>> {
161 None
162 }
92 fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output; 163 fn eval(ctx: &QueryCtx, params: &Self::Params) -> Self::Output;
93} 164}
94 165
166#[derive(Debug)]
95pub(crate) struct DbFiles { 167pub(crate) struct DbFiles {
96 db: Db, 168 db: Arc<Db>,
97} 169}
98 170
99impl DbFiles { 171impl DbFiles {
@@ -113,7 +185,7 @@ impl Query for Files {
113} 185}
114impl Get for Files { 186impl Get for Files {
115 fn get(ctx: &QueryCtx, _params: &()) -> DbFiles { 187 fn get(ctx: &QueryCtx, _params: &()) -> DbFiles {
116 DbFiles { db: ctx.db.clone() } 188 DbFiles { db: Arc::clone(&ctx.db) }
117 } 189 }
118} 190}
119 191
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 68cf31e08..3e77006c5 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -13,7 +13,7 @@ extern crate im;
13 13
14mod symbol_index; 14mod symbol_index;
15mod module_map; 15mod module_map;
16mod module_map_db; 16pub(crate) mod module_map_db;
17mod imp; 17mod imp;
18mod job; 18mod job;
19mod roots; 19mod roots;
diff --git a/crates/libanalysis/src/module_map_db.rs b/crates/libanalysis/src/module_map_db.rs
index 25dbe8dd4..14b156b43 100644
--- a/crates/libanalysis/src/module_map_db.rs
+++ b/crates/libanalysis/src/module_map_db.rs
@@ -1,11 +1,14 @@
1use std::sync::Arc; 1use std::sync::Arc;
2use { 2use {
3 FileId, 3 FileId,
4 db::{Query, Eval, QueryCtx, FileSyntax, Files}, 4 db::{
5 Query, Eval, QueryCtx, FileSyntax, Files,
6 Cache, QueryCache,
7 },
5 module_map::resolve_submodule, 8 module_map::resolve_submodule,
6}; 9};
7 10
8enum ModuleDescr {} 11pub(crate) enum ModuleDescr {}
9impl Query for ModuleDescr { 12impl Query for ModuleDescr {
10 const ID: u32 = 30; 13 const ID: u32 = 30;
11 type Params = FileId; 14 type Params = FileId;
@@ -27,6 +30,9 @@ impl Query for ParentModule {
27} 30}
28 31
29impl Eval for ModuleDescr { 32impl Eval for ModuleDescr {
33 fn cache(cache: &mut Cache) -> Option<&mut QueryCache<Self>> {
34 Some(&mut cache.module_descr)
35 }
30 fn eval(ctx: &QueryCtx, file_id: &FileId) -> Arc<descr::ModuleDescr> { 36 fn eval(ctx: &QueryCtx, file_id: &FileId) -> Arc<descr::ModuleDescr> {
31 let file = ctx.get::<FileSyntax>(file_id); 37 let file = ctx.get::<FileSyntax>(file_id);
32 Arc::new(descr::ModuleDescr::new(file.ast())) 38 Arc::new(descr::ModuleDescr::new(file.ast()))
@@ -66,6 +72,7 @@ mod descr {
66 ast::{self, NameOwner}, 72 ast::{self, NameOwner},
67 }; 73 };
68 74
75 #[derive(Debug)]
69 pub struct ModuleDescr { 76 pub struct ModuleDescr {
70 pub submodules: Vec<Submodule> 77 pub submodules: Vec<Submodule>
71 } 78 }
@@ -85,7 +92,7 @@ mod descr {
85 ModuleDescr { submodules } } 92 ModuleDescr { submodules } }
86 } 93 }
87 94
88 #[derive(Clone, Hash)] 95 #[derive(Clone, Hash, PartialEq, Eq, Debug)]
89 pub struct Submodule { 96 pub struct Submodule {
90 pub name: SmolStr, 97 pub name: SmolStr,
91 } 98 }
@@ -98,7 +105,7 @@ mod tests {
98 use im; 105 use im;
99 use relative_path::{RelativePath, RelativePathBuf}; 106 use relative_path::{RelativePath, RelativePathBuf};
100 use { 107 use {
101 db::{Query, Db, TraceEventKind}, 108 db::{Query, DbHost, TraceEventKind},
102 imp::FileResolverImp, 109 imp::FileResolverImp,
103 FileId, FileResolver, 110 FileId, FileResolver,
104 }; 111 };
@@ -122,7 +129,7 @@ mod tests {
122 struct Fixture { 129 struct Fixture {
123 next_file_id: u32, 130 next_file_id: u32,
124 fm: im::HashMap<FileId, RelativePathBuf>, 131 fm: im::HashMap<FileId, RelativePathBuf>,
125 db: Db, 132 db: DbHost,
126 } 133 }
127 134
128 impl Fixture { 135 impl Fixture {
@@ -130,7 +137,7 @@ mod tests {
130 Fixture { 137 Fixture {
131 next_file_id: 1, 138 next_file_id: 1,
132 fm: im::HashMap::new(), 139 fm: im::HashMap::new(),
133 db: Db::new(), 140 db: DbHost::new(),
134 } 141 }
135 } 142 }
136 fn add_file(&mut self, path: &str, text: &str) -> FileId { 143 fn add_file(&mut self, path: &str, text: &str) -> FileId {
@@ -185,10 +192,11 @@ mod tests {
185 fn test_parent_module() { 192 fn test_parent_module() {
186 let mut f = Fixture::new(); 193 let mut f = Fixture::new();
187 let foo = f.add_file("/foo.rs", ""); 194 let foo = f.add_file("/foo.rs", "");
188 f.check_parent_modules(foo, &[], &[(FileSyntax::ID, 1)]); 195 f.check_parent_modules(foo, &[], &[(ModuleDescr::ID, 1)]);
189 196
190 let lib = f.add_file("/lib.rs", "mod foo;"); 197 let lib = f.add_file("/lib.rs", "mod foo;");
191 f.check_parent_modules(foo, &[lib], &[(FileSyntax::ID, 2)]); 198 f.check_parent_modules(foo, &[lib], &[(ModuleDescr::ID, 2)]);
199 f.check_parent_modules(foo, &[lib], &[(ModuleDescr::ID, 0)]);
192 200
193 f.change_file(lib, ""); 201 f.change_file(lib, "");
194 f.check_parent_modules(foo, &[], &[(ModuleDescr::ID, 2)]); 202 f.check_parent_modules(foo, &[], &[(ModuleDescr::ID, 2)]);