diff options
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 153 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 200 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 58 |
4 files changed, 211 insertions, 204 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index b42f10071..4a3e0fed2 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | FnSignature, FnScopes, | 10 | FnSignature, FnScopes, |
11 | macros::MacroExpansion, | 11 | macros::MacroExpansion, |
12 | module_tree::{ModuleId, ModuleTree}, | 12 | module_tree::{ModuleId, ModuleTree}, |
13 | nameres::{ItemMap, InputModuleItems}, | 13 | nameres::{ItemMap, lower::InputModuleItems}, |
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, | 14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, |
15 | adt::{StructData, EnumData, EnumVariantData}, | 15 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 16 | impl_block::ModuleImplBlocks, |
@@ -58,7 +58,7 @@ pub trait HirDatabase: | |||
58 | #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] | 58 | #[salsa::invoke(crate::module_tree::Submodule::submodules_query)] |
59 | fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; | 59 | fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; |
60 | 60 | ||
61 | #[salsa::invoke(query_definitions::input_module_items)] | 61 | #[salsa::invoke(crate::nameres::lower::InputModuleItems::input_module_items_query)] |
62 | fn input_module_items( | 62 | fn input_module_items( |
63 | &self, | 63 | &self, |
64 | source_root_id: SourceRootId, | 64 | source_root_id: SourceRootId, |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 484f668d0..aea95e08c 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -14,23 +14,20 @@ | |||
14 | //! modifications (that is, typing inside a function should not change IMIs), | 14 | //! modifications (that is, typing inside a function should not change IMIs), |
15 | //! so that the results of name resolution can be preserved unless the module | 15 | //! so that the results of name resolution can be preserved unless the module |
16 | //! structure itself is modified. | 16 | //! structure itself is modified. |
17 | pub(crate) mod lower; | ||
18 | use lower::*; | ||
19 | |||
17 | use std::sync::Arc; | 20 | use std::sync::Arc; |
18 | 21 | ||
19 | use rustc_hash::{FxHashMap, FxHashSet}; | 22 | use rustc_hash::{FxHashMap, FxHashSet}; |
20 | use ra_syntax::{ | 23 | use ra_syntax::SyntaxKind::*; |
21 | TextRange, | 24 | use ra_db::SourceRootId; |
22 | SyntaxKind::{self, *}, | ||
23 | ast::{self, AstNode} | ||
24 | }; | ||
25 | use ra_db::{SourceRootId, FileId}; | ||
26 | 25 | ||
27 | use crate::{ | 26 | use crate::{ |
28 | HirFileId, | ||
29 | DefId, DefLoc, DefKind, | 27 | DefId, DefLoc, DefKind, |
30 | SourceItemId, SourceFileItemId, SourceFileItems, | ||
31 | Path, PathKind, | 28 | Path, PathKind, |
32 | HirDatabase, Crate, | 29 | HirDatabase, Crate, |
33 | Name, AsName, | 30 | Name, |
34 | module_tree::{ModuleId, ModuleTree}, | 31 | module_tree::{ModuleId, ModuleTree}, |
35 | }; | 32 | }; |
36 | 33 | ||
@@ -56,64 +53,6 @@ impl ModuleScope { | |||
56 | } | 53 | } |
57 | } | 54 | } |
58 | 55 | ||
59 | /// A set of items and imports declared inside a module, without relation to | ||
60 | /// other modules. | ||
61 | /// | ||
62 | /// This sits in-between raw syntax and name resolution and allows us to avoid | ||
63 | /// recomputing name res: if two instance of `InputModuleItems` are the same, we | ||
64 | /// can avoid redoing name resolution. | ||
65 | #[derive(Debug, Default, PartialEq, Eq)] | ||
66 | pub struct InputModuleItems { | ||
67 | pub(crate) items: Vec<ModuleItem>, | ||
68 | imports: Vec<Import>, | ||
69 | } | ||
70 | |||
71 | #[derive(Debug, PartialEq, Eq)] | ||
72 | pub(crate) struct ModuleItem { | ||
73 | pub(crate) id: SourceItemId, | ||
74 | pub(crate) name: Name, | ||
75 | kind: SyntaxKind, | ||
76 | vis: Vis, | ||
77 | } | ||
78 | |||
79 | #[derive(Debug, PartialEq, Eq)] | ||
80 | enum Vis { | ||
81 | // Priv, | ||
82 | Other, | ||
83 | } | ||
84 | |||
85 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
86 | struct Import { | ||
87 | path: Path, | ||
88 | kind: ImportKind, | ||
89 | } | ||
90 | |||
91 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
92 | pub struct NamedImport { | ||
93 | pub file_item_id: SourceFileItemId, | ||
94 | pub relative_range: TextRange, | ||
95 | } | ||
96 | |||
97 | impl NamedImport { | ||
98 | // FIXME: this is only here for one use-case in completion. Seems like a | ||
99 | // pretty gross special case. | ||
100 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | ||
101 | let source_item_id = SourceItemId { | ||
102 | file_id: file_id.into(), | ||
103 | item_id: Some(self.file_item_id), | ||
104 | }; | ||
105 | let syntax = db.file_item(source_item_id); | ||
106 | let offset = syntax.range().start(); | ||
107 | self.relative_range + offset | ||
108 | } | ||
109 | } | ||
110 | |||
111 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
112 | enum ImportKind { | ||
113 | Glob, | ||
114 | Named(NamedImport), | ||
115 | } | ||
116 | |||
117 | /// `Resolution` is basically `DefId` atm, but it should account for stuff like | 56 | /// `Resolution` is basically `DefId` atm, but it should account for stuff like |
118 | /// multiple namespaces, ambiguity and errors. | 57 | /// multiple namespaces, ambiguity and errors. |
119 | #[derive(Debug, Clone, PartialEq, Eq)] | 58 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -210,86 +149,6 @@ impl<T> PerNs<T> { | |||
210 | } | 149 | } |
211 | } | 150 | } |
212 | 151 | ||
213 | impl InputModuleItems { | ||
214 | pub(crate) fn add_item( | ||
215 | &mut self, | ||
216 | file_id: HirFileId, | ||
217 | file_items: &SourceFileItems, | ||
218 | item: &ast::ModuleItem, | ||
219 | ) -> Option<()> { | ||
220 | match item.kind() { | ||
221 | ast::ModuleItemKind::StructDef(it) => { | ||
222 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
223 | } | ||
224 | ast::ModuleItemKind::EnumDef(it) => { | ||
225 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
226 | } | ||
227 | ast::ModuleItemKind::FnDef(it) => { | ||
228 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
229 | } | ||
230 | ast::ModuleItemKind::TraitDef(it) => { | ||
231 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
232 | } | ||
233 | ast::ModuleItemKind::TypeDef(it) => { | ||
234 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
235 | } | ||
236 | ast::ModuleItemKind::ImplBlock(_) => { | ||
237 | // impls don't define items | ||
238 | } | ||
239 | ast::ModuleItemKind::UseItem(it) => self.add_use_item(file_items, it), | ||
240 | ast::ModuleItemKind::ExternCrateItem(_) => { | ||
241 | // TODO | ||
242 | } | ||
243 | ast::ModuleItemKind::ConstDef(it) => { | ||
244 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
245 | } | ||
246 | ast::ModuleItemKind::StaticDef(it) => { | ||
247 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
248 | } | ||
249 | ast::ModuleItemKind::Module(it) => { | ||
250 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
251 | } | ||
252 | } | ||
253 | Some(()) | ||
254 | } | ||
255 | |||
256 | fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) { | ||
257 | let file_item_id = file_items.id_of_unchecked(item.syntax()); | ||
258 | let start_offset = item.syntax().range().start(); | ||
259 | Path::expand_use_item(item, |path, range| { | ||
260 | let kind = match range { | ||
261 | None => ImportKind::Glob, | ||
262 | Some(range) => ImportKind::Named(NamedImport { | ||
263 | file_item_id, | ||
264 | relative_range: range - start_offset, | ||
265 | }), | ||
266 | }; | ||
267 | self.imports.push(Import { kind, path }) | ||
268 | }) | ||
269 | } | ||
270 | } | ||
271 | |||
272 | impl ModuleItem { | ||
273 | fn new( | ||
274 | file_id: HirFileId, | ||
275 | file_items: &SourceFileItems, | ||
276 | item: &impl ast::NameOwner, | ||
277 | ) -> Option<ModuleItem> { | ||
278 | let name = item.name()?.as_name(); | ||
279 | let kind = item.syntax().kind(); | ||
280 | let vis = Vis::Other; | ||
281 | let item_id = Some(file_items.id_of_unchecked(item.syntax())); | ||
282 | let id = SourceItemId { file_id, item_id }; | ||
283 | let res = ModuleItem { | ||
284 | id, | ||
285 | name, | ||
286 | kind, | ||
287 | vis, | ||
288 | }; | ||
289 | Some(res) | ||
290 | } | ||
291 | } | ||
292 | |||
293 | pub(crate) struct Resolver<'a, DB> { | 152 | pub(crate) struct Resolver<'a, DB> { |
294 | db: &'a DB, | 153 | db: &'a DB, |
295 | input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>, | 154 | input: &'a FxHashMap<ModuleId, Arc<InputModuleItems>>, |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs new file mode 100644 index 000000000..dd3bf245f --- /dev/null +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -0,0 +1,200 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_syntax::{ | ||
4 | TextRange, SyntaxKind, AstNode, | ||
5 | ast::{self, ModuleItemOwner}, | ||
6 | }; | ||
7 | use ra_db::{FileId, SourceRootId}; | ||
8 | |||
9 | use crate::{ | ||
10 | SourceItemId, SourceFileItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | ||
11 | HirFileId, MacroCallLoc, AsName, | ||
12 | module_tree::ModuleId | ||
13 | }; | ||
14 | /// A set of items and imports declared inside a module, without relation to | ||
15 | /// other modules. | ||
16 | /// | ||
17 | /// This sits in-between raw syntax and name resolution and allows us to avoid | ||
18 | /// recomputing name res: if two instance of `InputModuleItems` are the same, we | ||
19 | /// can avoid redoing name resolution. | ||
20 | #[derive(Debug, Default, PartialEq, Eq)] | ||
21 | pub struct InputModuleItems { | ||
22 | pub(crate) items: Vec<ModuleItem>, | ||
23 | pub(super) imports: Vec<Import>, | ||
24 | } | ||
25 | |||
26 | impl InputModuleItems { | ||
27 | pub(crate) fn input_module_items_query( | ||
28 | db: &impl HirDatabase, | ||
29 | source_root_id: SourceRootId, | ||
30 | module_id: ModuleId, | ||
31 | ) -> Arc<InputModuleItems> { | ||
32 | let module_tree = db.module_tree(source_root_id); | ||
33 | let source = module_id.source(&module_tree); | ||
34 | let file_id = source.file_id; | ||
35 | let source = ModuleSource::from_source_item_id(db, source); | ||
36 | let file_items = db.file_items(file_id); | ||
37 | let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| { | ||
38 | for item in items { | ||
39 | match item { | ||
40 | ast::ItemOrMacro::Item(it) => { | ||
41 | acc.add_item(file_id, &file_items, it); | ||
42 | } | ||
43 | ast::ItemOrMacro::Macro(macro_call) => { | ||
44 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | ||
45 | let loc = MacroCallLoc { | ||
46 | source_root_id, | ||
47 | module_id, | ||
48 | source_item_id: SourceItemId { | ||
49 | file_id, | ||
50 | item_id: Some(item_id), | ||
51 | }, | ||
52 | }; | ||
53 | let id = loc.id(db); | ||
54 | let file_id = HirFileId::from(id); | ||
55 | let file_items = db.file_items(file_id); | ||
56 | //FIXME: expand recursively | ||
57 | for item in db.hir_source_file(file_id).items() { | ||
58 | acc.add_item(file_id, &file_items, item); | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | let mut res = InputModuleItems::default(); | ||
66 | match source { | ||
67 | ModuleSource::SourceFile(it) => fill(&mut res, &mut it.items_with_macros()), | ||
68 | ModuleSource::Module(it) => { | ||
69 | if let Some(item_list) = it.item_list() { | ||
70 | fill(&mut res, &mut item_list.items_with_macros()) | ||
71 | } | ||
72 | } | ||
73 | }; | ||
74 | Arc::new(res) | ||
75 | } | ||
76 | |||
77 | pub(crate) fn add_item( | ||
78 | &mut self, | ||
79 | file_id: HirFileId, | ||
80 | file_items: &SourceFileItems, | ||
81 | item: &ast::ModuleItem, | ||
82 | ) -> Option<()> { | ||
83 | match item.kind() { | ||
84 | ast::ModuleItemKind::StructDef(it) => { | ||
85 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
86 | } | ||
87 | ast::ModuleItemKind::EnumDef(it) => { | ||
88 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
89 | } | ||
90 | ast::ModuleItemKind::FnDef(it) => { | ||
91 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
92 | } | ||
93 | ast::ModuleItemKind::TraitDef(it) => { | ||
94 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
95 | } | ||
96 | ast::ModuleItemKind::TypeDef(it) => { | ||
97 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
98 | } | ||
99 | ast::ModuleItemKind::ImplBlock(_) => { | ||
100 | // impls don't define items | ||
101 | } | ||
102 | ast::ModuleItemKind::UseItem(it) => self.add_use_item(file_items, it), | ||
103 | ast::ModuleItemKind::ExternCrateItem(_) => { | ||
104 | // TODO | ||
105 | } | ||
106 | ast::ModuleItemKind::ConstDef(it) => { | ||
107 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
108 | } | ||
109 | ast::ModuleItemKind::StaticDef(it) => { | ||
110 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
111 | } | ||
112 | ast::ModuleItemKind::Module(it) => { | ||
113 | self.items.push(ModuleItem::new(file_id, file_items, it)?) | ||
114 | } | ||
115 | } | ||
116 | Some(()) | ||
117 | } | ||
118 | |||
119 | fn add_use_item(&mut self, file_items: &SourceFileItems, item: &ast::UseItem) { | ||
120 | let file_item_id = file_items.id_of_unchecked(item.syntax()); | ||
121 | let start_offset = item.syntax().range().start(); | ||
122 | Path::expand_use_item(item, |path, range| { | ||
123 | let kind = match range { | ||
124 | None => ImportKind::Glob, | ||
125 | Some(range) => ImportKind::Named(NamedImport { | ||
126 | file_item_id, | ||
127 | relative_range: range - start_offset, | ||
128 | }), | ||
129 | }; | ||
130 | self.imports.push(Import { kind, path }) | ||
131 | }) | ||
132 | } | ||
133 | } | ||
134 | |||
135 | #[derive(Debug, PartialEq, Eq)] | ||
136 | pub(super) enum Vis { | ||
137 | // Priv, | ||
138 | Other, | ||
139 | } | ||
140 | |||
141 | #[derive(Debug, PartialEq, Eq)] | ||
142 | pub(crate) struct ModuleItem { | ||
143 | pub(crate) id: SourceItemId, | ||
144 | pub(crate) name: Name, | ||
145 | pub(super) kind: SyntaxKind, | ||
146 | pub(super) vis: Vis, | ||
147 | } | ||
148 | |||
149 | impl ModuleItem { | ||
150 | fn new( | ||
151 | file_id: HirFileId, | ||
152 | file_items: &SourceFileItems, | ||
153 | item: &impl ast::NameOwner, | ||
154 | ) -> Option<ModuleItem> { | ||
155 | let name = item.name()?.as_name(); | ||
156 | let kind = item.syntax().kind(); | ||
157 | let vis = Vis::Other; | ||
158 | let item_id = Some(file_items.id_of_unchecked(item.syntax())); | ||
159 | let id = SourceItemId { file_id, item_id }; | ||
160 | let res = ModuleItem { | ||
161 | id, | ||
162 | name, | ||
163 | kind, | ||
164 | vis, | ||
165 | }; | ||
166 | Some(res) | ||
167 | } | ||
168 | } | ||
169 | |||
170 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
171 | pub(super) struct Import { | ||
172 | pub(super) path: Path, | ||
173 | pub(super) kind: ImportKind, | ||
174 | } | ||
175 | |||
176 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
177 | pub struct NamedImport { | ||
178 | pub file_item_id: SourceFileItemId, | ||
179 | pub relative_range: TextRange, | ||
180 | } | ||
181 | |||
182 | impl NamedImport { | ||
183 | // FIXME: this is only here for one use-case in completion. Seems like a | ||
184 | // pretty gross special case. | ||
185 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | ||
186 | let source_item_id = SourceItemId { | ||
187 | file_id: file_id.into(), | ||
188 | item_id: Some(self.file_item_id), | ||
189 | }; | ||
190 | let syntax = db.file_item(source_item_id); | ||
191 | let offset = syntax.range().start(); | ||
192 | self.relative_range + offset | ||
193 | } | ||
194 | } | ||
195 | |||
196 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
197 | pub(super) enum ImportKind { | ||
198 | Glob, | ||
199 | Named(NamedImport), | ||
200 | } | ||
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 24cb5c752..985a02410 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -6,16 +6,14 @@ use std::{ | |||
6 | use rustc_hash::FxHashMap; | 6 | use rustc_hash::FxHashMap; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | AstNode, SyntaxNode, TreeArc, | 8 | AstNode, SyntaxNode, TreeArc, |
9 | ast::{self, ModuleItemOwner} | ||
10 | }; | 9 | }; |
11 | use ra_db::SourceRootId; | 10 | use ra_db::SourceRootId; |
12 | 11 | ||
13 | use crate::{ | 12 | use crate::{ |
14 | SourceFileItems, SourceItemId, DefId, HirFileId, ModuleSource, | 13 | SourceFileItems, SourceItemId, DefId, HirFileId, |
15 | MacroCallLoc, FnScopes, | 14 | FnScopes, |
16 | db::HirDatabase, | 15 | db::HirDatabase, |
17 | module_tree::ModuleId, | 16 | nameres::{ItemMap, Resolver}, |
18 | nameres::{InputModuleItems, ItemMap, Resolver}, | ||
19 | }; | 17 | }; |
20 | 18 | ||
21 | pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { | 19 | pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { |
@@ -43,56 +41,6 @@ pub(super) fn file_item( | |||
43 | } | 41 | } |
44 | } | 42 | } |
45 | 43 | ||
46 | pub(super) fn input_module_items( | ||
47 | db: &impl HirDatabase, | ||
48 | source_root_id: SourceRootId, | ||
49 | module_id: ModuleId, | ||
50 | ) -> Arc<InputModuleItems> { | ||
51 | let module_tree = db.module_tree(source_root_id); | ||
52 | let source = module_id.source(&module_tree); | ||
53 | let file_id = source.file_id; | ||
54 | let source = ModuleSource::from_source_item_id(db, source); | ||
55 | let file_items = db.file_items(file_id); | ||
56 | let fill = |acc: &mut InputModuleItems, items: &mut Iterator<Item = ast::ItemOrMacro>| { | ||
57 | for item in items { | ||
58 | match item { | ||
59 | ast::ItemOrMacro::Item(it) => { | ||
60 | acc.add_item(file_id, &file_items, it); | ||
61 | } | ||
62 | ast::ItemOrMacro::Macro(macro_call) => { | ||
63 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | ||
64 | let loc = MacroCallLoc { | ||
65 | source_root_id, | ||
66 | module_id, | ||
67 | source_item_id: SourceItemId { | ||
68 | file_id, | ||
69 | item_id: Some(item_id), | ||
70 | }, | ||
71 | }; | ||
72 | let id = loc.id(db); | ||
73 | let file_id = HirFileId::from(id); | ||
74 | let file_items = db.file_items(file_id); | ||
75 | //FIXME: expand recursively | ||
76 | for item in db.hir_source_file(file_id).items() { | ||
77 | acc.add_item(file_id, &file_items, item); | ||
78 | } | ||
79 | } | ||
80 | } | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | let mut res = InputModuleItems::default(); | ||
85 | match source { | ||
86 | ModuleSource::SourceFile(it) => fill(&mut res, &mut it.items_with_macros()), | ||
87 | ModuleSource::Module(it) => { | ||
88 | if let Some(item_list) = it.item_list() { | ||
89 | fill(&mut res, &mut item_list.items_with_macros()) | ||
90 | } | ||
91 | } | ||
92 | }; | ||
93 | Arc::new(res) | ||
94 | } | ||
95 | |||
96 | pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> { | 44 | pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> { |
97 | let start = Instant::now(); | 45 | let start = Instant::now(); |
98 | let module_tree = db.module_tree(source_root); | 46 | let module_tree = db.module_tree(source_root); |