diff options
Diffstat (limited to 'crates/ra_analysis/src/db')
-rw-r--r-- | crates/ra_analysis/src/db/imp.rs | 153 | ||||
-rw-r--r-- | crates/ra_analysis/src/db/mod.rs | 85 |
2 files changed, 0 insertions, 238 deletions
diff --git a/crates/ra_analysis/src/db/imp.rs b/crates/ra_analysis/src/db/imp.rs deleted file mode 100644 index 7669b6184..000000000 --- a/crates/ra_analysis/src/db/imp.rs +++ /dev/null | |||
@@ -1,153 +0,0 @@ | |||
1 | use std::{ | ||
2 | sync::Arc, | ||
3 | any::Any, | ||
4 | hash::{Hash, Hasher}, | ||
5 | collections::hash_map::{DefaultHasher}, | ||
6 | iter, | ||
7 | }; | ||
8 | use rustc_hash::FxHashMap; | ||
9 | use salsa; | ||
10 | use crate::{FileId, imp::FileResolverImp}; | ||
11 | use super::{State, Query, QueryCtx}; | ||
12 | |||
13 | pub(super) type Data = Arc<Any + Send + Sync + 'static>; | ||
14 | |||
15 | #[derive(Debug)] | ||
16 | pub(super) struct Db { | ||
17 | names: Arc<FxHashMap<salsa::QueryTypeId, &'static str>>, | ||
18 | pub(super) imp: salsa::Db<State, Data>, | ||
19 | } | ||
20 | |||
21 | impl Db { | ||
22 | pub(super) fn new(mut reg: QueryRegistry) -> Db { | ||
23 | let config = reg.config.take().unwrap(); | ||
24 | Db { | ||
25 | names: Arc::new(reg.names), | ||
26 | imp: salsa::Db::new(config, State::default()) | ||
27 | } | ||
28 | } | ||
29 | pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { | ||
30 | let names = self.names.clone(); | ||
31 | let mut invalidations = salsa::Invalidations::new(); | ||
32 | invalidations.invalidate(FILE_TEXT, changed_files.iter().map(hash).map(salsa::InputFingerprint)); | ||
33 | if resolver_changed { | ||
34 | invalidations.invalidate(FILE_SET, iter::once(salsa::InputFingerprint(hash(&())))); | ||
35 | } else { | ||
36 | invalidations.invalidate(FILE_SET, iter::empty()); | ||
37 | } | ||
38 | let imp = self.imp.with_ground_data( | ||
39 | new_state, | ||
40 | invalidations, | ||
41 | ); | ||
42 | Db { names, imp } | ||
43 | } | ||
44 | pub(super) fn extract_trace(&self, ctx: &salsa::QueryCtx<State, Data>) -> Vec<&'static str> { | ||
45 | ctx.trace().into_iter().map(|it| self.names[&it]).collect() | ||
46 | } | ||
47 | } | ||
48 | |||
49 | pub(crate) trait EvalQuery { | ||
50 | type Params; | ||
51 | type Output; | ||
52 | fn query_type(&self) -> salsa::QueryTypeId; | ||
53 | fn f(&self) -> salsa::QueryFn<State, Data>; | ||
54 | fn get(&self, ctx: &QueryCtx, params: Self::Params) -> Arc<Self::Output>; | ||
55 | } | ||
56 | |||
57 | impl<T, R> EvalQuery for Query<T, R> | ||
58 | where | ||
59 | T: Hash + Send + Sync + 'static, | ||
60 | R: Hash + Send + Sync + 'static, | ||
61 | { | ||
62 | type Params = T; | ||
63 | type Output = R; | ||
64 | fn query_type(&self) -> salsa::QueryTypeId { | ||
65 | salsa::QueryTypeId(self.0) | ||
66 | } | ||
67 | fn f(&self) -> salsa::QueryFn<State, Data> { | ||
68 | let f = self.1; | ||
69 | Box::new(move |ctx, data| { | ||
70 | let ctx = QueryCtx { imp: ctx }; | ||
71 | let data: &T = data.downcast_ref().unwrap(); | ||
72 | let res = f(ctx, data); | ||
73 | let h = hash(&res); | ||
74 | (Arc::new(res), salsa::OutputFingerprint(h)) | ||
75 | }) | ||
76 | } | ||
77 | fn get(&self, ctx: &QueryCtx, params: Self::Params) -> Arc<Self::Output> { | ||
78 | let query_id = salsa::QueryId( | ||
79 | self.query_type(), | ||
80 | salsa::InputFingerprint(hash(¶ms)), | ||
81 | ); | ||
82 | let res = ctx.imp.get(query_id, Arc::new(params)); | ||
83 | res.downcast().unwrap() | ||
84 | } | ||
85 | } | ||
86 | |||
87 | pub(super) struct QueryRegistry { | ||
88 | config: Option<salsa::QueryConfig<State, Data>>, | ||
89 | names: FxHashMap<salsa::QueryTypeId, &'static str>, | ||
90 | } | ||
91 | |||
92 | impl QueryRegistry { | ||
93 | pub(super) fn new() -> QueryRegistry { | ||
94 | let mut config = salsa::QueryConfig::<State, Data>::new(); | ||
95 | config = config.with_ground_query( | ||
96 | FILE_TEXT, Box::new(|state, params| { | ||
97 | let file_id: &FileId = params.downcast_ref().unwrap(); | ||
98 | let res = state.file_map[file_id].clone(); | ||
99 | let fingerprint = salsa::OutputFingerprint(hash(&res)); | ||
100 | (res, fingerprint) | ||
101 | }) | ||
102 | ); | ||
103 | config = config.with_ground_query( | ||
104 | FILE_SET, Box::new(|state, _params| { | ||
105 | let file_ids: Vec<FileId> = state.file_map.keys().cloned().collect(); | ||
106 | let hash = hash(&file_ids); | ||
107 | let file_resolver = state.file_resolver.clone(); | ||
108 | let res = (file_ids, file_resolver); | ||
109 | let fingerprint = salsa::OutputFingerprint(hash); | ||
110 | (Arc::new(res), fingerprint) | ||
111 | }) | ||
112 | ); | ||
113 | let mut names = FxHashMap::default(); | ||
114 | names.insert(FILE_TEXT, "FILE_TEXT"); | ||
115 | names.insert(FILE_SET, "FILE_SET"); | ||
116 | QueryRegistry { config: Some(config), names } | ||
117 | } | ||
118 | pub(super) fn add<Q: EvalQuery>(&mut self, q: Q, name: &'static str) { | ||
119 | let id = q.query_type(); | ||
120 | let prev = self.names.insert(id, name); | ||
121 | assert!(prev.is_none(), "duplicate query: {:?}", id); | ||
122 | let config = self.config.take().unwrap(); | ||
123 | let config = config.with_query(id, q.f()); | ||
124 | self.config= Some(config); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | fn hash<T: Hash>(x: &T) -> u64 { | ||
129 | let mut hasher = DefaultHasher::new(); | ||
130 | x.hash(&mut hasher); | ||
131 | hasher.finish() | ||
132 | } | ||
133 | |||
134 | const FILE_TEXT: salsa::QueryTypeId = salsa::QueryTypeId(0); | ||
135 | pub(super) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> { | ||
136 | let query_id = salsa::QueryId( | ||
137 | FILE_TEXT, | ||
138 | salsa::InputFingerprint(hash(&file_id)), | ||
139 | ); | ||
140 | let res = ctx.imp.get(query_id, Arc::new(file_id)); | ||
141 | res.downcast().unwrap() | ||
142 | } | ||
143 | |||
144 | const FILE_SET: salsa::QueryTypeId = salsa::QueryTypeId(1); | ||
145 | pub(super) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> { | ||
146 | let query_id = salsa::QueryId( | ||
147 | FILE_SET, | ||
148 | salsa::InputFingerprint(hash(&())), | ||
149 | ); | ||
150 | let res = ctx.imp.get(query_id, Arc::new(())); | ||
151 | res.downcast().unwrap() | ||
152 | } | ||
153 | |||
diff --git a/crates/ra_analysis/src/db/mod.rs b/crates/ra_analysis/src/db/mod.rs deleted file mode 100644 index 4eb7d922d..000000000 --- a/crates/ra_analysis/src/db/mod.rs +++ /dev/null | |||
@@ -1,85 +0,0 @@ | |||
1 | mod imp; | ||
2 | |||
3 | use std::{ | ||
4 | sync::Arc, | ||
5 | }; | ||
6 | use im; | ||
7 | use salsa; | ||
8 | use crate::{FileId, imp::FileResolverImp}; | ||
9 | |||
10 | #[derive(Debug, Default, Clone)] | ||
11 | pub(crate) struct State { | ||
12 | pub(crate) file_map: im::HashMap<FileId, Arc<String>>, | ||
13 | pub(crate) file_resolver: FileResolverImp | ||
14 | } | ||
15 | |||
16 | #[derive(Debug)] | ||
17 | pub(crate) struct Db { | ||
18 | imp: imp::Db, | ||
19 | } | ||
20 | |||
21 | #[derive(Clone, Copy)] | ||
22 | pub(crate) struct QueryCtx<'a> { | ||
23 | imp: &'a salsa::QueryCtx<State, imp::Data>, | ||
24 | } | ||
25 | |||
26 | pub(crate) struct Query<T, R>(pub(crate) u16, pub(crate) fn(QueryCtx, &T) -> R); | ||
27 | |||
28 | pub(crate) struct QueryRegistry { | ||
29 | imp: imp::QueryRegistry, | ||
30 | } | ||
31 | |||
32 | impl Default for Db { | ||
33 | fn default() -> Db { | ||
34 | Db::new() | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl Db { | ||
39 | pub(crate) fn new() -> Db { | ||
40 | let reg = QueryRegistry::new(); | ||
41 | Db { imp: imp::Db::new(reg.imp) } | ||
42 | } | ||
43 | pub(crate) fn state(&self) -> &State { | ||
44 | self.imp.imp.ground_data() | ||
45 | } | ||
46 | pub(crate) fn with_changes(&self, new_state: State, changed_files: &[FileId], resolver_changed: bool) -> Db { | ||
47 | Db { imp: self.imp.with_changes(new_state, changed_files, resolver_changed) } | ||
48 | } | ||
49 | pub(crate) fn make_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> R { | ||
50 | let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; | ||
51 | f(ctx) | ||
52 | } | ||
53 | #[allow(unused)] | ||
54 | pub(crate) fn trace_query<F: FnOnce(QueryCtx) -> R, R>(&self, f: F) -> (R, Vec<&'static str>) { | ||
55 | let ctx = QueryCtx { imp: &self.imp.imp.query_ctx() }; | ||
56 | let res = f(ctx); | ||
57 | let trace = self.imp.extract_trace(ctx.imp); | ||
58 | (res, trace) | ||
59 | } | ||
60 | } | ||
61 | |||
62 | impl<'a> QueryCtx<'a> { | ||
63 | pub(crate) fn get<Q: imp::EvalQuery>(&self, q: Q, params: Q::Params) -> Arc<Q::Output> { | ||
64 | q.get(self, params) | ||
65 | } | ||
66 | } | ||
67 | |||
68 | pub(crate) fn file_text(ctx: QueryCtx, file_id: FileId) -> Arc<String> { | ||
69 | imp::file_text(ctx, file_id) | ||
70 | } | ||
71 | |||
72 | pub(crate) fn file_set(ctx: QueryCtx) -> Arc<(Vec<FileId>, FileResolverImp)> { | ||
73 | imp::file_set(ctx) | ||
74 | } | ||
75 | impl QueryRegistry { | ||
76 | fn new() -> QueryRegistry { | ||
77 | let mut reg = QueryRegistry { imp: imp::QueryRegistry::new() }; | ||
78 | crate::queries::register_queries(&mut reg); | ||
79 | crate::module_map::register_queries(&mut reg); | ||
80 | reg | ||
81 | } | ||
82 | pub(crate) fn add<Q: imp::EvalQuery>(&mut self, q: Q, name: &'static str) { | ||
83 | self.imp.add(q, name) | ||
84 | } | ||
85 | } | ||