aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/nameres.rs153
-rw-r--r--crates/ra_hir/src/nameres/lower.rs200
-rw-r--r--crates/ra_hir/src/query_definitions.rs58
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.
17pub(crate) mod lower;
18use lower::*;
19
17use std::sync::Arc; 20use std::sync::Arc;
18 21
19use rustc_hash::{FxHashMap, FxHashSet}; 22use rustc_hash::{FxHashMap, FxHashSet};
20use ra_syntax::{ 23use ra_syntax::SyntaxKind::*;
21 TextRange, 24use ra_db::SourceRootId;
22 SyntaxKind::{self, *},
23 ast::{self, AstNode}
24};
25use ra_db::{SourceRootId, FileId};
26 25
27use crate::{ 26use 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)]
66pub struct InputModuleItems {
67 pub(crate) items: Vec<ModuleItem>,
68 imports: Vec<Import>,
69}
70
71#[derive(Debug, PartialEq, Eq)]
72pub(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)]
80enum Vis {
81 // Priv,
82 Other,
83}
84
85#[derive(Debug, Clone, PartialEq, Eq)]
86struct Import {
87 path: Path,
88 kind: ImportKind,
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92pub struct NamedImport {
93 pub file_item_id: SourceFileItemId,
94 pub relative_range: TextRange,
95}
96
97impl 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)]
112enum 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
213impl 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
272impl 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
293pub(crate) struct Resolver<'a, DB> { 152pub(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 @@
1use std::sync::Arc;
2
3use ra_syntax::{
4 TextRange, SyntaxKind, AstNode,
5 ast::{self, ModuleItemOwner},
6};
7use ra_db::{FileId, SourceRootId};
8
9use 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)]
21pub struct InputModuleItems {
22 pub(crate) items: Vec<ModuleItem>,
23 pub(super) imports: Vec<Import>,
24}
25
26impl 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)]
136pub(super) enum Vis {
137 // Priv,
138 Other,
139}
140
141#[derive(Debug, PartialEq, Eq)]
142pub(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
149impl 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)]
171pub(super) struct Import {
172 pub(super) path: Path,
173 pub(super) kind: ImportKind,
174}
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq)]
177pub struct NamedImport {
178 pub file_item_id: SourceFileItemId,
179 pub relative_range: TextRange,
180}
181
182impl 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)]
197pub(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::{
6use rustc_hash::FxHashMap; 6use rustc_hash::FxHashMap;
7use ra_syntax::{ 7use ra_syntax::{
8 AstNode, SyntaxNode, TreeArc, 8 AstNode, SyntaxNode, TreeArc,
9 ast::{self, ModuleItemOwner}
10}; 9};
11use ra_db::SourceRootId; 10use ra_db::SourceRootId;
12 11
13use crate::{ 12use 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
21pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { 19pub(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
46pub(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
96pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> { 44pub(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);