diff options
author | Florian Diebold <[email protected]> | 2018-12-24 19:32:39 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2018-12-25 14:16:42 +0000 |
commit | 4ff161852016c6c15954d6f30bd637834a2b2b68 (patch) | |
tree | 7ea2d34a8f58f5a242481e6d6294bef22546fcaf /crates/ra_hir/src/module | |
parent | b5b68f2094d49cacde6d7f0c49f521a0b25f34bd (diff) |
Do name resolution by namespace (types/values)
Diffstat (limited to 'crates/ra_hir/src/module')
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 154 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres/tests.rs | 6 |
2 files changed, 121 insertions, 39 deletions
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 0b152a406..33c9d93c2 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -118,22 +118,96 @@ enum ImportKind { | |||
118 | #[derive(Debug, Clone, PartialEq, Eq)] | 118 | #[derive(Debug, Clone, PartialEq, Eq)] |
119 | pub struct Resolution { | 119 | pub struct Resolution { |
120 | /// None for unresolved | 120 | /// None for unresolved |
121 | pub def_id: Option<DefId>, | 121 | pub def_id: PerNs<DefId>, |
122 | /// ident by whitch this is imported into local scope. | 122 | /// ident by whitch this is imported into local scope. |
123 | pub import: Option<NamedImport>, | 123 | pub import: Option<NamedImport>, |
124 | } | 124 | } |
125 | 125 | ||
126 | // #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] | 126 | #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] |
127 | // enum Namespace { | 127 | pub enum Namespace { |
128 | // Types, | 128 | Types, |
129 | // Values, | 129 | Values, |
130 | // } | 130 | } |
131 | |||
132 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | ||
133 | pub struct PerNs<T> { | ||
134 | pub types: Option<T>, | ||
135 | pub values: Option<T>, | ||
136 | } | ||
137 | |||
138 | impl<T> PerNs<T> { | ||
139 | pub fn none() -> PerNs<T> { | ||
140 | PerNs { | ||
141 | types: None, | ||
142 | values: None, | ||
143 | } | ||
144 | } | ||
145 | |||
146 | pub fn values(t: T) -> PerNs<T> { | ||
147 | PerNs { | ||
148 | types: None, | ||
149 | values: Some(t), | ||
150 | } | ||
151 | } | ||
152 | |||
153 | pub fn types(t: T) -> PerNs<T> { | ||
154 | PerNs { | ||
155 | types: Some(t), | ||
156 | values: None, | ||
157 | } | ||
158 | } | ||
159 | |||
160 | pub fn both(types: T, values: T) -> PerNs<T> { | ||
161 | PerNs { | ||
162 | types: Some(types), | ||
163 | values: Some(values), | ||
164 | } | ||
165 | } | ||
166 | |||
167 | pub fn is_none(&self) -> bool { | ||
168 | self.types.is_none() && self.values.is_none() | ||
169 | } | ||
170 | |||
171 | pub fn take(self, namespace: Namespace) -> Option<T> { | ||
172 | match namespace { | ||
173 | Namespace::Types => self.types, | ||
174 | Namespace::Values => self.values, | ||
175 | } | ||
176 | } | ||
177 | |||
178 | pub fn take_types(self) -> Option<T> { | ||
179 | self.types | ||
180 | } | ||
181 | |||
182 | pub fn take_values(self) -> Option<T> { | ||
183 | self.values | ||
184 | } | ||
131 | 185 | ||
132 | // #[derive(Debug)] | 186 | pub fn get(&self, namespace: Namespace) -> Option<&T> { |
133 | // struct PerNs<T> { | 187 | self.as_ref().take(namespace) |
134 | // types: Option<T>, | 188 | } |
135 | // values: Option<T>, | 189 | |
136 | // } | 190 | pub fn as_ref(&self) -> PerNs<&T> { |
191 | PerNs { | ||
192 | types: self.types.as_ref(), | ||
193 | values: self.values.as_ref(), | ||
194 | } | ||
195 | } | ||
196 | |||
197 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { | ||
198 | PerNs { | ||
199 | types: self.types.and_then(&f), | ||
200 | values: self.values.and_then(&f), | ||
201 | } | ||
202 | } | ||
203 | |||
204 | pub fn map<U>(self, f: impl Fn(T) -> U) -> PerNs<U> { | ||
205 | PerNs { | ||
206 | types: self.types.map(&f), | ||
207 | values: self.values.map(&f), | ||
208 | } | ||
209 | } | ||
210 | } | ||
137 | 211 | ||
138 | impl InputModuleItems { | 212 | impl InputModuleItems { |
139 | pub(crate) fn new<'a>( | 213 | pub(crate) fn new<'a>( |
@@ -254,7 +328,7 @@ where | |||
254 | for dep in krate.dependencies(self.db) { | 328 | for dep in krate.dependencies(self.db) { |
255 | if let Some(module) = dep.krate.root_module(self.db)? { | 329 | if let Some(module) = dep.krate.root_module(self.db)? { |
256 | let def_id = module.def_id(self.db); | 330 | let def_id = module.def_id(self.db); |
257 | self.add_module_item(&mut module_items, dep.name, def_id); | 331 | self.add_module_item(&mut module_items, dep.name, PerNs::types(def_id)); |
258 | } | 332 | } |
259 | } | 333 | } |
260 | }; | 334 | }; |
@@ -265,7 +339,7 @@ where | |||
265 | module_items.items.insert( | 339 | module_items.items.insert( |
266 | name.clone(), | 340 | name.clone(), |
267 | Resolution { | 341 | Resolution { |
268 | def_id: None, | 342 | def_id: PerNs::none(), |
269 | import: Some(import), | 343 | import: Some(import), |
270 | }, | 344 | }, |
271 | ); | 345 | ); |
@@ -277,18 +351,23 @@ where | |||
277 | if item.kind == MODULE { | 351 | if item.kind == MODULE { |
278 | continue; | 352 | continue; |
279 | } | 353 | } |
280 | let def_loc = DefLoc { | 354 | // depending on the item kind, the location can define something in |
281 | kind: DefKind::for_syntax_kind(item.kind).unwrap_or(DefKind::Item), | 355 | // the values namespace, the types namespace, or both |
282 | source_root_id: self.source_root, | 356 | let kind = DefKind::for_syntax_kind(item.kind); |
283 | module_id, | 357 | let def_id = kind.map(|k| { |
284 | source_item_id: SourceItemId { | 358 | let def_loc = DefLoc { |
285 | file_id, | 359 | kind: k, |
286 | item_id: Some(item.id), | 360 | source_root_id: self.source_root, |
287 | }, | 361 | module_id, |
288 | }; | 362 | source_item_id: SourceItemId { |
289 | let def_id = def_loc.id(self.db); | 363 | file_id, |
364 | item_id: Some(item.id), | ||
365 | }, | ||
366 | }; | ||
367 | def_loc.id(self.db) | ||
368 | }); | ||
290 | let resolution = Resolution { | 369 | let resolution = Resolution { |
291 | def_id: Some(def_id), | 370 | def_id, |
292 | import: None, | 371 | import: None, |
293 | }; | 372 | }; |
294 | module_items.items.insert(item.name.clone(), resolution); | 373 | module_items.items.insert(item.name.clone(), resolution); |
@@ -303,16 +382,16 @@ where | |||
303 | source_item_id: module_id.source(&self.module_tree).0, | 382 | source_item_id: module_id.source(&self.module_tree).0, |
304 | }; | 383 | }; |
305 | let def_id = def_loc.id(self.db); | 384 | let def_id = def_loc.id(self.db); |
306 | self.add_module_item(&mut module_items, name, def_id); | 385 | self.add_module_item(&mut module_items, name, PerNs::types(def_id)); |
307 | } | 386 | } |
308 | 387 | ||
309 | self.result.per_module.insert(module_id, module_items); | 388 | self.result.per_module.insert(module_id, module_items); |
310 | Ok(()) | 389 | Ok(()) |
311 | } | 390 | } |
312 | 391 | ||
313 | fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: DefId) { | 392 | fn add_module_item(&self, module_items: &mut ModuleScope, name: SmolStr, def_id: PerNs<DefId>) { |
314 | let resolution = Resolution { | 393 | let resolution = Resolution { |
315 | def_id: Some(def_id), | 394 | def_id, |
316 | import: None, | 395 | import: None, |
317 | }; | 396 | }; |
318 | module_items.items.insert(name, resolution); | 397 | module_items.items.insert(name, resolution); |
@@ -347,15 +426,17 @@ where | |||
347 | let is_last = i == import.path.segments.len() - 1; | 426 | let is_last = i == import.path.segments.len() - 1; |
348 | 427 | ||
349 | let def_id = match self.result.per_module[&curr].items.get(name) { | 428 | let def_id = match self.result.per_module[&curr].items.get(name) { |
350 | None => return Ok(()), | 429 | Some(res) if !res.def_id.is_none() => res.def_id, |
351 | Some(res) => match res.def_id { | 430 | _ => return Ok(()), |
352 | Some(it) => it, | ||
353 | None => return Ok(()), | ||
354 | }, | ||
355 | }; | 431 | }; |
356 | 432 | ||
357 | if !is_last { | 433 | if !is_last { |
358 | curr = match def_id.loc(self.db) { | 434 | let type_def_id = if let Some(d) = def_id.take(Namespace::Types) { |
435 | d | ||
436 | } else { | ||
437 | return Ok(()); | ||
438 | }; | ||
439 | curr = match type_def_id.loc(self.db) { | ||
359 | DefLoc { | 440 | DefLoc { |
360 | kind: DefKind::Module, | 441 | kind: DefKind::Module, |
361 | module_id: target_module_id, | 442 | module_id: target_module_id, |
@@ -370,10 +451,11 @@ where | |||
370 | segments: import.path.segments[i + 1..].iter().cloned().collect(), | 451 | segments: import.path.segments[i + 1..].iter().cloned().collect(), |
371 | kind: PathKind::Crate, | 452 | kind: PathKind::Crate, |
372 | }; | 453 | }; |
373 | if let Some(def_id) = module.resolve_path(self.db, path)? { | 454 | let def_id = module.resolve_path(self.db, path)?; |
455 | if !def_id.is_none() { | ||
374 | self.update(module_id, |items| { | 456 | self.update(module_id, |items| { |
375 | let res = Resolution { | 457 | let res = Resolution { |
376 | def_id: Some(def_id), | 458 | def_id: def_id, |
377 | import: Some(ptr), | 459 | import: Some(ptr), |
378 | }; | 460 | }; |
379 | items.items.insert(name.clone(), res); | 461 | items.items.insert(name.clone(), res); |
@@ -387,7 +469,7 @@ where | |||
387 | } else { | 469 | } else { |
388 | self.update(module_id, |items| { | 470 | self.update(module_id, |items| { |
389 | let res = Resolution { | 471 | let res = Resolution { |
390 | def_id: Some(def_id), | 472 | def_id: def_id, |
391 | import: Some(ptr), | 473 | import: Some(ptr), |
392 | }; | 474 | }; |
393 | items.items.insert(name.clone(), res); | 475 | items.items.insert(name.clone(), res); |
diff --git a/crates/ra_hir/src/module/nameres/tests.rs b/crates/ra_hir/src/module/nameres/tests.rs index 3e29c3954..03ea5c1d6 100644 --- a/crates/ra_hir/src/module/nameres/tests.rs +++ b/crates/ra_hir/src/module/nameres/tests.rs | |||
@@ -40,7 +40,7 @@ fn item_map_smoke_test() { | |||
40 | ); | 40 | ); |
41 | let name = SmolStr::from("Baz"); | 41 | let name = SmolStr::from("Baz"); |
42 | let resolution = &item_map.per_module[&module_id].items[&name]; | 42 | let resolution = &item_map.per_module[&module_id].items[&name]; |
43 | assert!(resolution.def_id.is_some()); | 43 | assert!(resolution.def_id.take_types().is_some()); |
44 | } | 44 | } |
45 | 45 | ||
46 | #[test] | 46 | #[test] |
@@ -59,7 +59,7 @@ fn test_self() { | |||
59 | ); | 59 | ); |
60 | let name = SmolStr::from("Baz"); | 60 | let name = SmolStr::from("Baz"); |
61 | let resolution = &item_map.per_module[&module_id].items[&name]; | 61 | let resolution = &item_map.per_module[&module_id].items[&name]; |
62 | assert!(resolution.def_id.is_some()); | 62 | assert!(resolution.def_id.take_types().is_some()); |
63 | } | 63 | } |
64 | 64 | ||
65 | #[test] | 65 | #[test] |
@@ -92,7 +92,7 @@ fn item_map_across_crates() { | |||
92 | 92 | ||
93 | let name = SmolStr::from("Baz"); | 93 | let name = SmolStr::from("Baz"); |
94 | let resolution = &item_map.per_module[&module_id].items[&name]; | 94 | let resolution = &item_map.per_module[&module_id].items[&name]; |
95 | assert!(resolution.def_id.is_some()); | 95 | assert!(resolution.def_id.take_types().is_some()); |
96 | } | 96 | } |
97 | 97 | ||
98 | #[test] | 98 | #[test] |