diff options
author | Aleksey Kladov <[email protected]> | 2018-09-15 11:38:31 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-09-15 22:00:05 +0100 |
commit | 47be3a3a24de1eb28e1575db1571d934765f6d53 (patch) | |
tree | 6653f5206a482f013fe0a6d4bb6d6dcc259f16fc /crates/libanalysis/src/module_map_db | |
parent | 8c737255ff876fc61f8dc8a7d33252476a4b4c8d (diff) |
renames
Diffstat (limited to 'crates/libanalysis/src/module_map_db')
-rw-r--r-- | crates/libanalysis/src/module_map_db/descr.rs | 29 | ||||
-rw-r--r-- | crates/libanalysis/src/module_map_db/mod.rs | 180 |
2 files changed, 209 insertions, 0 deletions
diff --git a/crates/libanalysis/src/module_map_db/descr.rs b/crates/libanalysis/src/module_map_db/descr.rs new file mode 100644 index 000000000..fb298a315 --- /dev/null +++ b/crates/libanalysis/src/module_map_db/descr.rs | |||
@@ -0,0 +1,29 @@ | |||
1 | use libsyntax2::{ | ||
2 | SmolStr, | ||
3 | ast::{self, NameOwner}, | ||
4 | }; | ||
5 | |||
6 | #[derive(Debug, Hash)] | ||
7 | pub struct ModuleDescr { | ||
8 | pub submodules: Vec<Submodule> | ||
9 | } | ||
10 | |||
11 | impl ModuleDescr { | ||
12 | pub fn new(root: ast::Root) -> ModuleDescr { | ||
13 | let submodules = root | ||
14 | .modules() | ||
15 | .filter_map(|module| { | ||
16 | let name = module.name()?.text(); | ||
17 | if !module.has_semi() { | ||
18 | return None; | ||
19 | } | ||
20 | Some(Submodule { name }) | ||
21 | }).collect(); | ||
22 | |||
23 | ModuleDescr { submodules } } | ||
24 | } | ||
25 | |||
26 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | ||
27 | pub struct Submodule { | ||
28 | pub name: SmolStr, | ||
29 | } | ||
diff --git a/crates/libanalysis/src/module_map_db/mod.rs b/crates/libanalysis/src/module_map_db/mod.rs new file mode 100644 index 000000000..777f7a38a --- /dev/null +++ b/crates/libanalysis/src/module_map_db/mod.rs | |||
@@ -0,0 +1,180 @@ | |||
1 | mod descr; | ||
2 | |||
3 | use std::sync::Arc; | ||
4 | use { | ||
5 | FileId, | ||
6 | db::{ | ||
7 | BoxedQuery, Query, QueryCtx | ||
8 | }, | ||
9 | module_map::resolve_submodule, | ||
10 | }; | ||
11 | |||
12 | pub(crate) fn queries(acc: &mut Vec<BoxedQuery>) { | ||
13 | acc.push(MODULE_DESCR.into()); | ||
14 | acc.push(RESOLVE_SUBMODULE.into()); | ||
15 | acc.push(PARENT_MODULE.into()); | ||
16 | } | ||
17 | |||
18 | impl<'a> QueryCtx<'a> { | ||
19 | fn module_descr(&self, file_id: FileId) -> Arc<descr::ModuleDescr> { | ||
20 | self.get(MODULE_DESCR, file_id) | ||
21 | } | ||
22 | fn resolve_submodule(&self, file_id: FileId, submod: descr::Submodule) -> Arc<Vec<FileId>> { | ||
23 | self.get(RESOLVE_SUBMODULE, (file_id, submod)) | ||
24 | } | ||
25 | } | ||
26 | |||
27 | pub(crate) const MODULE_DESCR: Query<FileId, descr::ModuleDescr> = Query { | ||
28 | id: 30, | ||
29 | f: |ctx, &file_id| { | ||
30 | let file = ctx.file_syntax(file_id); | ||
31 | descr::ModuleDescr::new(file.ast()) | ||
32 | } | ||
33 | }; | ||
34 | |||
35 | pub(crate) const RESOLVE_SUBMODULE: Query<(FileId, descr::Submodule), Vec<FileId>> = Query { | ||
36 | id: 31, | ||
37 | f: |ctx, params| { | ||
38 | let files = ctx.file_set(); | ||
39 | resolve_submodule(params.0, ¶ms.1.name, &files.1).0 | ||
40 | } | ||
41 | }; | ||
42 | |||
43 | pub(crate) const PARENT_MODULE: Query<FileId, Vec<FileId>> = Query { | ||
44 | id: 40, | ||
45 | f: |ctx, file_id| { | ||
46 | let files = ctx.file_set(); | ||
47 | let res = files.0.iter() | ||
48 | .map(|&parent_id| (parent_id, ctx.module_descr(parent_id))) | ||
49 | .filter(|(parent_id, descr)| { | ||
50 | descr.submodules.iter() | ||
51 | .any(|subm| { | ||
52 | ctx.resolve_submodule(*parent_id, subm.clone()) | ||
53 | .iter() | ||
54 | .any(|it| it == file_id) | ||
55 | }) | ||
56 | }) | ||
57 | .map(|(id, _)| id) | ||
58 | .collect(); | ||
59 | res | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | #[cfg(test)] | ||
64 | mod tests { | ||
65 | use std::collections::HashMap; | ||
66 | use im; | ||
67 | use relative_path::{RelativePath, RelativePathBuf}; | ||
68 | use { | ||
69 | db::{Query, Db, State}, | ||
70 | imp::FileResolverImp, | ||
71 | FileId, FileResolver, | ||
72 | }; | ||
73 | use super::*; | ||
74 | |||
75 | #[derive(Debug)] | ||
76 | struct FileMap(im::HashMap<FileId, RelativePathBuf>); | ||
77 | |||
78 | impl FileResolver for FileMap { | ||
79 | fn file_stem(&self, file_id: FileId) -> String { | ||
80 | self.0[&file_id].file_stem().unwrap().to_string() | ||
81 | } | ||
82 | fn resolve(&self, file_id: FileId, rel: &RelativePath) -> Option<FileId> { | ||
83 | let path = self.0[&file_id].join(rel).normalize(); | ||
84 | self.0.iter() | ||
85 | .filter_map(|&(id, ref p)| Some(id).filter(|_| p == &path)) | ||
86 | .next() | ||
87 | } | ||
88 | } | ||
89 | |||
90 | struct Fixture { | ||
91 | next_file_id: u32, | ||
92 | fm: im::HashMap<FileId, RelativePathBuf>, | ||
93 | db: Db, | ||
94 | } | ||
95 | |||
96 | impl Fixture { | ||
97 | fn new() -> Fixture { | ||
98 | Fixture { | ||
99 | next_file_id: 1, | ||
100 | fm: im::HashMap::new(), | ||
101 | db: Db::new(State::default()), | ||
102 | } | ||
103 | } | ||
104 | fn add_file(&mut self, path: &str, text: &str) -> FileId { | ||
105 | assert!(path.starts_with("/")); | ||
106 | let file_id = FileId(self.next_file_id); | ||
107 | self.next_file_id += 1; | ||
108 | self.fm.insert(file_id, RelativePathBuf::from(&path[1..])); | ||
109 | let mut new_state = self.db.state().clone(); | ||
110 | new_state.file_map.insert(file_id, text.to_string().into_boxed_str().into()); | ||
111 | new_state.resolver = FileResolverImp::new( | ||
112 | Arc::new(FileMap(self.fm.clone())) | ||
113 | ); | ||
114 | self.db = self.db.with_state(new_state, &[file_id], true); | ||
115 | file_id | ||
116 | } | ||
117 | fn remove_file(&mut self, file_id: FileId) { | ||
118 | self.fm.remove(&file_id); | ||
119 | let mut new_state = self.db.state().clone(); | ||
120 | new_state.file_map.remove(&file_id); | ||
121 | new_state.resolver = FileResolverImp::new( | ||
122 | Arc::new(FileMap(self.fm.clone())) | ||
123 | ); | ||
124 | self.db = self.db.with_state(new_state, &[file_id], true); | ||
125 | } | ||
126 | fn change_file(&mut self, file_id: FileId, new_text: &str) { | ||
127 | let mut new_state = self.db.state().clone(); | ||
128 | new_state.file_map.insert(file_id, new_text.to_string().into_boxed_str().into()); | ||
129 | self.db = self.db.with_state(new_state, &[file_id], false); | ||
130 | } | ||
131 | fn check_parent_modules( | ||
132 | &self, | ||
133 | file_id: FileId, | ||
134 | expected: &[FileId], | ||
135 | queries: &[(u16, u64)] | ||
136 | ) { | ||
137 | let (actual, events) = self.db.get(PARENT_MODULE, file_id); | ||
138 | assert_eq!(actual.as_slice(), expected); | ||
139 | let mut counts = HashMap::new(); | ||
140 | events.into_iter() | ||
141 | .for_each(|event| *counts.entry(event).or_insert(0) += 1); | ||
142 | for &(query_id, expected_count) in queries.iter() { | ||
143 | let actual_count = *counts.get(&query_id).unwrap_or(&0); | ||
144 | assert_eq!( | ||
145 | actual_count, | ||
146 | expected_count, | ||
147 | "counts for {} differ", | ||
148 | query_id, | ||
149 | ) | ||
150 | } | ||
151 | |||
152 | } | ||
153 | } | ||
154 | |||
155 | #[test] | ||
156 | fn test_parent_module() { | ||
157 | let mut f = Fixture::new(); | ||
158 | let foo = f.add_file("/foo.rs", ""); | ||
159 | f.check_parent_modules(foo, &[], &[(MODULE_DESCR.id, 1)]); | ||
160 | |||
161 | let lib = f.add_file("/lib.rs", "mod foo;"); | ||
162 | f.check_parent_modules(foo, &[lib], &[(MODULE_DESCR.id, 1)]); | ||
163 | f.check_parent_modules(foo, &[lib], &[(MODULE_DESCR.id, 0)]); | ||
164 | |||
165 | f.change_file(lib, ""); | ||
166 | f.check_parent_modules(foo, &[], &[(MODULE_DESCR.id, 1)]); | ||
167 | |||
168 | f.change_file(lib, "mod foo;"); | ||
169 | f.check_parent_modules(foo, &[lib], &[(MODULE_DESCR.id, 1)]); | ||
170 | |||
171 | f.change_file(lib, "mod bar;"); | ||
172 | f.check_parent_modules(foo, &[], &[(MODULE_DESCR.id, 1)]); | ||
173 | |||
174 | f.change_file(lib, "mod foo;"); | ||
175 | f.check_parent_modules(foo, &[lib], &[(MODULE_DESCR.id, 1)]); | ||
176 | |||
177 | f.remove_file(lib); | ||
178 | f.check_parent_modules(foo, &[], &[(MODULE_DESCR.id, 0)]); | ||
179 | } | ||
180 | } | ||