diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/collector.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/crate_def_map/raw.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 190 |
3 files changed, 27 insertions, 188 deletions
diff --git a/crates/ra_hir/src/nameres/crate_def_map/collector.rs b/crates/ra_hir/src/nameres/crate_def_map/collector.rs index 8b727e2c9..0f500ce42 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/collector.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/collector.rs | |||
@@ -224,7 +224,7 @@ where | |||
224 | } | 224 | } |
225 | } | 225 | } |
226 | let resolution = Resolution { def, import: Some(import_id) }; | 226 | let resolution = Resolution { def, import: Some(import_id) }; |
227 | self.update(module_id, None, &[(name, resolution)]); | 227 | self.update(module_id, Some(import_id), &[(name, resolution)]); |
228 | } | 228 | } |
229 | } | 229 | } |
230 | 230 | ||
@@ -262,6 +262,13 @@ where | |||
262 | existing.import = import.or(res.import); | 262 | existing.import = import.or(res.import); |
263 | changed = true; | 263 | changed = true; |
264 | } | 264 | } |
265 | if existing.def.is_none() | ||
266 | && res.def.is_none() | ||
267 | && existing.import.is_none() | ||
268 | && res.import.is_some() | ||
269 | { | ||
270 | existing.import = res.import; | ||
271 | } | ||
265 | } | 272 | } |
266 | if !changed { | 273 | if !changed { |
267 | return; | 274 | return; |
diff --git a/crates/ra_hir/src/nameres/crate_def_map/raw.rs b/crates/ra_hir/src/nameres/crate_def_map/raw.rs index f064f722c..dca86e394 100644 --- a/crates/ra_hir/src/nameres/crate_def_map/raw.rs +++ b/crates/ra_hir/src/nameres/crate_def_map/raw.rs | |||
@@ -14,6 +14,7 @@ use ra_syntax::{ | |||
14 | use crate::{ | 14 | use crate::{ |
15 | PersistentHirDatabase, Name, AsName, Path, HirFileId, | 15 | PersistentHirDatabase, Name, AsName, Path, HirFileId, |
16 | ids::{SourceFileItemId, SourceFileItems}, | 16 | ids::{SourceFileItemId, SourceFileItems}, |
17 | nameres::lower::ImportSourceMap, | ||
17 | }; | 18 | }; |
18 | 19 | ||
19 | #[derive(Debug, Default, PartialEq, Eq)] | 20 | #[derive(Debug, Default, PartialEq, Eq)] |
@@ -31,13 +32,21 @@ impl RawItems { | |||
31 | db: &impl PersistentHirDatabase, | 32 | db: &impl PersistentHirDatabase, |
32 | file_id: FileId, | 33 | file_id: FileId, |
33 | ) -> Arc<RawItems> { | 34 | ) -> Arc<RawItems> { |
35 | db.raw_items_with_source_map(file_id).0 | ||
36 | } | ||
37 | |||
38 | pub(crate) fn raw_items_with_source_map_query( | ||
39 | db: &impl PersistentHirDatabase, | ||
40 | file_id: FileId, | ||
41 | ) -> (Arc<RawItems>, Arc<ImportSourceMap>) { | ||
34 | let mut collector = RawItemsCollector { | 42 | let mut collector = RawItemsCollector { |
35 | raw_items: RawItems::default(), | 43 | raw_items: RawItems::default(), |
36 | source_file_items: db.file_items(file_id.into()), | 44 | source_file_items: db.file_items(file_id.into()), |
45 | source_map: ImportSourceMap::default(), | ||
37 | }; | 46 | }; |
38 | let source_file = db.parse(file_id); | 47 | let source_file = db.parse(file_id); |
39 | collector.process_module(None, &*source_file); | 48 | collector.process_module(None, &*source_file); |
40 | Arc::new(collector.raw_items) | 49 | (Arc::new(collector.raw_items), Arc::new(collector.source_map)) |
41 | } | 50 | } |
42 | 51 | ||
43 | pub(crate) fn items(&self) -> &[RawItem] { | 52 | pub(crate) fn items(&self) -> &[RawItem] { |
@@ -51,6 +60,7 @@ impl RawItems { | |||
51 | let mut collector = RawItemsCollector { | 60 | let mut collector = RawItemsCollector { |
52 | raw_items: RawItems::default(), | 61 | raw_items: RawItems::default(), |
53 | source_file_items: Arc::new(source_file_items), | 62 | source_file_items: Arc::new(source_file_items), |
63 | source_map: ImportSourceMap::default(), | ||
54 | }; | 64 | }; |
55 | collector.process_module(None, &*source_file); | 65 | collector.process_module(None, &*source_file); |
56 | collector.raw_items | 66 | collector.raw_items |
@@ -144,6 +154,7 @@ pub(crate) struct MacroData { | |||
144 | struct RawItemsCollector { | 154 | struct RawItemsCollector { |
145 | raw_items: RawItems, | 155 | raw_items: RawItems, |
146 | source_file_items: Arc<SourceFileItems>, | 156 | source_file_items: Arc<SourceFileItems>, |
157 | source_map: ImportSourceMap, | ||
147 | } | 158 | } |
148 | 159 | ||
149 | impl RawItemsCollector { | 160 | impl RawItemsCollector { |
@@ -227,6 +238,9 @@ impl RawItemsCollector { | |||
227 | is_prelude, | 238 | is_prelude, |
228 | is_extern_crate: false, | 239 | is_extern_crate: false, |
229 | }); | 240 | }); |
241 | if let Some(segment) = segment { | ||
242 | self.source_map.insert(import, segment) | ||
243 | } | ||
230 | self.push_item(current_module, RawItem::Import(import)) | 244 | self.push_item(current_module, RawItem::Import(import)) |
231 | }) | 245 | }) |
232 | } | 246 | } |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 24707aed1..d4c7f2481 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -1,18 +1,10 @@ | |||
1 | use std::sync::Arc; | ||
2 | |||
3 | use ra_syntax::{ | 1 | use ra_syntax::{ |
4 | AstNode, SourceFile, TreeArc, AstPtr, | 2 | AstNode, SourceFile, TreeArc, AstPtr, |
5 | ast::{self, ModuleItemOwner, NameOwner, AttrsOwner}, | 3 | ast, |
6 | }; | 4 | }; |
7 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | 5 | use ra_arena::{RawId, impl_arena_id, map::ArenaMap}; |
8 | use rustc_hash::FxHashMap; | ||
9 | 6 | ||
10 | use crate::{ | 7 | use crate::{Path, ModuleSource, Name}; |
11 | SourceItemId, Path, ModuleSource, Name, | ||
12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, | ||
13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, TypeAlias, | ||
14 | ids::LocationCtx, PersistentHirDatabase, | ||
15 | }; | ||
16 | 8 | ||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 9 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
18 | pub struct ImportId(RawId); | 10 | pub struct ImportId(RawId); |
@@ -27,25 +19,13 @@ pub struct ImportData { | |||
27 | pub(super) is_extern_crate: bool, | 19 | pub(super) is_extern_crate: bool, |
28 | } | 20 | } |
29 | 21 | ||
30 | /// A set of items and imports declared inside a module, without relation to | ||
31 | /// other modules. | ||
32 | /// | ||
33 | /// This sits in-between raw syntax and name resolution and allows us to avoid | ||
34 | /// recomputing name res: if two instance of `InputModuleItems` are the same, we | ||
35 | /// can avoid redoing name resolution. | ||
36 | #[derive(Debug, Default, PartialEq, Eq)] | ||
37 | pub struct LoweredModule { | ||
38 | pub(crate) declarations: FxHashMap<Name, PerNs<ModuleDef>>, | ||
39 | pub(super) imports: Arena<ImportId, ImportData>, | ||
40 | } | ||
41 | |||
42 | #[derive(Debug, Default, PartialEq, Eq)] | 22 | #[derive(Debug, Default, PartialEq, Eq)] |
43 | pub struct ImportSourceMap { | 23 | pub struct ImportSourceMap { |
44 | map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, | 24 | map: ArenaMap<ImportId, AstPtr<ast::PathSegment>>, |
45 | } | 25 | } |
46 | 26 | ||
47 | impl ImportSourceMap { | 27 | impl ImportSourceMap { |
48 | fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { | 28 | pub(crate) fn insert(&mut self, import: ImportId, segment: &ast::PathSegment) { |
49 | self.map.insert(import, AstPtr::new(segment)) | 29 | self.map.insert(import, AstPtr::new(segment)) |
50 | } | 30 | } |
51 | 31 | ||
@@ -58,165 +38,3 @@ impl ImportSourceMap { | |||
58 | self.map[import].to_node(file).to_owned() | 38 | self.map[import].to_node(file).to_owned() |
59 | } | 39 | } |
60 | } | 40 | } |
61 | |||
62 | impl LoweredModule { | ||
63 | pub(crate) fn lower_module_query( | ||
64 | db: &impl PersistentHirDatabase, | ||
65 | module: Module, | ||
66 | ) -> Arc<LoweredModule> { | ||
67 | db.lower_module_with_source_map(module).0 | ||
68 | } | ||
69 | |||
70 | pub(crate) fn lower_module_with_source_map_query( | ||
71 | db: &impl PersistentHirDatabase, | ||
72 | module: Module, | ||
73 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | ||
74 | let (file_id, source) = module.definition_source(db); | ||
75 | let file_id: HirFileId = file_id.into(); | ||
76 | let mut source_map = ImportSourceMap::default(); | ||
77 | let mut res = LoweredModule::default(); | ||
78 | match source { | ||
79 | ModuleSource::SourceFile(it) => { | ||
80 | res.fill(&mut source_map, db, module, file_id, &mut it.items_with_macros()) | ||
81 | } | ||
82 | ModuleSource::Module(it) => { | ||
83 | if let Some(item_list) = it.item_list() { | ||
84 | res.fill( | ||
85 | &mut source_map, | ||
86 | db, | ||
87 | module, | ||
88 | file_id, | ||
89 | &mut item_list.items_with_macros(), | ||
90 | ) | ||
91 | } | ||
92 | } | ||
93 | }; | ||
94 | (Arc::new(res), Arc::new(source_map)) | ||
95 | } | ||
96 | |||
97 | fn fill( | ||
98 | &mut self, | ||
99 | source_map: &mut ImportSourceMap, | ||
100 | db: &impl PersistentHirDatabase, | ||
101 | module: Module, | ||
102 | file_id: HirFileId, | ||
103 | items: &mut Iterator<Item = ast::ItemOrMacro>, | ||
104 | ) { | ||
105 | let file_items = db.file_items(file_id); | ||
106 | |||
107 | for item in items { | ||
108 | match item { | ||
109 | ast::ItemOrMacro::Item(it) => { | ||
110 | self.add_def_id(source_map, db, module, file_id, it); | ||
111 | } | ||
112 | ast::ItemOrMacro::Macro(macro_call) => { | ||
113 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | ||
114 | let loc = | ||
115 | MacroCallLoc { module, source_item_id: SourceItemId { file_id, item_id } }; | ||
116 | let id = loc.id(db); | ||
117 | let file_id = HirFileId::from(id); | ||
118 | //FIXME: expand recursively | ||
119 | for item in db.hir_parse(file_id).items() { | ||
120 | self.add_def_id(source_map, db, module, file_id, item); | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | fn add_def_id( | ||
128 | &mut self, | ||
129 | source_map: &mut ImportSourceMap, | ||
130 | db: &impl PersistentHirDatabase, | ||
131 | module: Module, | ||
132 | file_id: HirFileId, | ||
133 | item: &ast::ModuleItem, | ||
134 | ) { | ||
135 | let ctx = LocationCtx::new(db, module, file_id); | ||
136 | match item.kind() { | ||
137 | ast::ModuleItemKind::StructDef(it) => { | ||
138 | if let Some(name) = it.name() { | ||
139 | let s = Struct { id: ctx.to_def(it) }; | ||
140 | let s: ModuleDef = s.into(); | ||
141 | self.declarations.insert(name.as_name(), PerNs::both(s, s)); | ||
142 | } | ||
143 | } | ||
144 | ast::ModuleItemKind::EnumDef(it) => { | ||
145 | if let Some(name) = it.name() { | ||
146 | let e = Enum { id: ctx.to_def(it) }; | ||
147 | let e: ModuleDef = e.into(); | ||
148 | self.declarations.insert(name.as_name(), PerNs::types(e)); | ||
149 | } | ||
150 | } | ||
151 | ast::ModuleItemKind::FnDef(it) => { | ||
152 | if let Some(name) = it.name() { | ||
153 | let func = Function { id: ctx.to_def(it) }; | ||
154 | self.declarations.insert(name.as_name(), PerNs::values(func.into())); | ||
155 | } | ||
156 | } | ||
157 | ast::ModuleItemKind::TraitDef(it) => { | ||
158 | if let Some(name) = it.name() { | ||
159 | let t = Trait { id: ctx.to_def(it) }; | ||
160 | self.declarations.insert(name.as_name(), PerNs::types(t.into())); | ||
161 | } | ||
162 | } | ||
163 | ast::ModuleItemKind::TypeAliasDef(it) => { | ||
164 | if let Some(name) = it.name() { | ||
165 | let t = TypeAlias { id: ctx.to_def(it) }; | ||
166 | self.declarations.insert(name.as_name(), PerNs::types(t.into())); | ||
167 | } | ||
168 | } | ||
169 | ast::ModuleItemKind::ImplBlock(_) => { | ||
170 | // impls don't define items | ||
171 | } | ||
172 | ast::ModuleItemKind::UseItem(it) => { | ||
173 | self.add_use_item(source_map, it); | ||
174 | } | ||
175 | ast::ModuleItemKind::ExternCrateItem(it) => { | ||
176 | if let Some(name_ref) = it.name_ref() { | ||
177 | let path = Path::from_name_ref(name_ref); | ||
178 | let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name); | ||
179 | self.imports.alloc(ImportData { | ||
180 | path, | ||
181 | alias, | ||
182 | is_glob: false, | ||
183 | is_prelude: false, | ||
184 | is_extern_crate: true, | ||
185 | }); | ||
186 | } | ||
187 | } | ||
188 | ast::ModuleItemKind::ConstDef(it) => { | ||
189 | if let Some(name) = it.name() { | ||
190 | let c = Const { id: ctx.to_def(it) }; | ||
191 | self.declarations.insert(name.as_name(), PerNs::values(c.into())); | ||
192 | } | ||
193 | } | ||
194 | ast::ModuleItemKind::StaticDef(it) => { | ||
195 | if let Some(name) = it.name() { | ||
196 | let s = Static { id: ctx.to_def(it) }; | ||
197 | self.declarations.insert(name.as_name(), PerNs::values(s.into())); | ||
198 | } | ||
199 | } | ||
200 | ast::ModuleItemKind::Module(_) => { | ||
201 | // modules are handled separately directly by name res | ||
202 | } | ||
203 | }; | ||
204 | } | ||
205 | |||
206 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | ||
207 | let is_prelude = | ||
208 | item.attrs().any(|attr| attr.as_atom().map(|s| s == "prelude_import").unwrap_or(false)); | ||
209 | Path::expand_use_item(item, |path, segment, alias| { | ||
210 | let import = self.imports.alloc(ImportData { | ||
211 | path, | ||
212 | alias, | ||
213 | is_glob: segment.is_none(), | ||
214 | is_prelude, | ||
215 | is_extern_crate: false, | ||
216 | }); | ||
217 | if let Some(segment) = segment { | ||
218 | source_map.insert(import, segment) | ||
219 | } | ||
220 | }) | ||
221 | } | ||
222 | } | ||