diff options
author | Florian Diebold <[email protected]> | 2019-02-03 22:23:22 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-04 20:49:34 +0000 |
commit | 1056b480d6235ee72849a416b84e13180f84307c (patch) | |
tree | 7c9cf6822357bff4bd4d2055f464bf9991c8e4a4 /crates/ra_hir | |
parent | d69023fc72b26e64ebf1f96fc322a2f7377a5f4d (diff) |
Make extern crates in the root module add to the extern prelude
To accomplish this, separate the extern prelude from the per-module item maps.
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 90 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 12 |
4 files changed, 68 insertions, 39 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 92ab0f692..a58bf8f87 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -134,7 +134,7 @@ impl Module { | |||
134 | } | 134 | } |
135 | 135 | ||
136 | /// Returns the crate this module is part of. | 136 | /// Returns the crate this module is part of. |
137 | pub fn krate(&self, _db: &impl HirDatabase) -> Option<Crate> { | 137 | pub fn krate(&self, _db: &impl PersistentHirDatabase) -> Option<Crate> { |
138 | Some(self.krate) | 138 | Some(self.krate) |
139 | } | 139 | } |
140 | 140 | ||
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 04cc693b3..68df083d8 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -34,6 +34,7 @@ use crate::{ | |||
34 | /// module, the set of visible items. | 34 | /// module, the set of visible items. |
35 | #[derive(Default, Debug, PartialEq, Eq)] | 35 | #[derive(Default, Debug, PartialEq, Eq)] |
36 | pub struct ItemMap { | 36 | pub struct ItemMap { |
37 | extern_prelude: FxHashMap<Name, ModuleDef>, | ||
37 | per_module: ArenaMap<ModuleId, ModuleScope>, | 38 | per_module: ArenaMap<ModuleId, ModuleScope>, |
38 | } | 39 | } |
39 | 40 | ||
@@ -204,6 +205,7 @@ where | |||
204 | } | 205 | } |
205 | 206 | ||
206 | pub(crate) fn resolve(mut self) -> ItemMap { | 207 | pub(crate) fn resolve(mut self) -> ItemMap { |
208 | self.populate_extern_prelude(); | ||
207 | for (&module_id, items) in self.input.iter() { | 209 | for (&module_id, items) in self.input.iter() { |
208 | self.populate_module(module_id, Arc::clone(items)); | 210 | self.populate_module(module_id, Arc::clone(items)); |
209 | } | 211 | } |
@@ -227,29 +229,19 @@ where | |||
227 | self.result | 229 | self.result |
228 | } | 230 | } |
229 | 231 | ||
232 | fn populate_extern_prelude(&mut self) { | ||
233 | for dep in self.krate.dependencies(self.db) { | ||
234 | log::debug!("crate dep {:?} -> {:?}", dep.name, dep.krate); | ||
235 | if let Some(module) = dep.krate.root_module(self.db) { | ||
236 | self.result | ||
237 | .extern_prelude | ||
238 | .insert(dep.name.clone(), module.into()); | ||
239 | } | ||
240 | } | ||
241 | } | ||
242 | |||
230 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) { | 243 | fn populate_module(&mut self, module_id: ModuleId, input: Arc<LoweredModule>) { |
231 | let mut module_items = ModuleScope::default(); | 244 | let mut module_items = ModuleScope::default(); |
232 | |||
233 | // Populate extern crates prelude | ||
234 | { | ||
235 | let root_id = module_id.crate_root(&self.module_tree); | ||
236 | let file_id = root_id.file_id(&self.module_tree); | ||
237 | let crate_graph = self.db.crate_graph(); | ||
238 | if let Some(crate_id) = crate_graph.crate_id_for_crate_root(file_id.as_original_file()) | ||
239 | { | ||
240 | let krate = Crate { crate_id }; | ||
241 | for dep in krate.dependencies(self.db) { | ||
242 | if let Some(module) = dep.krate.root_module(self.db) { | ||
243 | let def = module.into(); | ||
244 | self.add_module_item( | ||
245 | &mut module_items, | ||
246 | dep.name.clone(), | ||
247 | PerNs::types(def), | ||
248 | ); | ||
249 | } | ||
250 | } | ||
251 | }; | ||
252 | } | ||
253 | for (import_id, import_data) in input.imports.iter() { | 245 | for (import_id, import_data) in input.imports.iter() { |
254 | if let Some(last_segment) = import_data.path.segments.iter().last() { | 246 | if let Some(last_segment) = import_data.path.segments.iter().last() { |
255 | if !import_data.is_glob { | 247 | if !import_data.is_glob { |
@@ -327,7 +319,16 @@ where | |||
327 | .alias | 319 | .alias |
328 | .clone() | 320 | .clone() |
329 | .unwrap_or_else(|| last_segment.name.clone()); | 321 | .unwrap_or_else(|| last_segment.name.clone()); |
330 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def,); | 322 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); |
323 | |||
324 | // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 | ||
325 | if let Some(root_module) = self.krate.root_module(self.db) { | ||
326 | if import.is_extern_crate && module_id == root_module.module_id { | ||
327 | if let Some(def) = def.take_types() { | ||
328 | self.result.extern_prelude.insert(name.clone(), def); | ||
329 | } | ||
330 | } | ||
331 | } | ||
331 | self.update(module_id, |items| { | 332 | self.update(module_id, |items| { |
332 | let res = Resolution { | 333 | let res = Resolution { |
333 | def, | 334 | def, |
@@ -389,24 +390,53 @@ impl ItemMap { | |||
389 | original_module: Module, | 390 | original_module: Module, |
390 | path: &Path, | 391 | path: &Path, |
391 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { | 392 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { |
392 | let mut curr_per_ns: PerNs<ModuleDef> = PerNs::types(match path.kind { | 393 | let mut segments = path.segments.iter().enumerate(); |
393 | PathKind::Crate => original_module.crate_root(db).into(), | 394 | let mut curr_per_ns: PerNs<ModuleDef> = match path.kind { |
394 | PathKind::Self_ | PathKind::Plain => original_module.into(), | 395 | PathKind::Crate => PerNs::types(original_module.crate_root(db).into()), |
396 | PathKind::Self_ => PerNs::types(original_module.into()), | ||
397 | PathKind::Plain => { | ||
398 | let segment = match segments.next() { | ||
399 | Some((_, segment)) => segment, | ||
400 | None => return (PerNs::none(), ReachedFixedPoint::Yes), | ||
401 | }; | ||
402 | // Resolve in: | ||
403 | // - current module / scope | ||
404 | // - extern prelude | ||
405 | match self[original_module.module_id].items.get(&segment.name) { | ||
406 | Some(res) if !res.def.is_none() => res.def, | ||
407 | _ => { | ||
408 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
409 | PerNs::types(*def) | ||
410 | } else { | ||
411 | return (PerNs::none(), ReachedFixedPoint::No); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | } | ||
395 | PathKind::Super => { | 416 | PathKind::Super => { |
396 | if let Some(p) = original_module.parent(db) { | 417 | if let Some(p) = original_module.parent(db) { |
397 | p.into() | 418 | PerNs::types(p.into()) |
398 | } else { | 419 | } else { |
399 | log::debug!("super path in root module"); | 420 | log::debug!("super path in root module"); |
400 | return (PerNs::none(), ReachedFixedPoint::Yes); | 421 | return (PerNs::none(), ReachedFixedPoint::Yes); |
401 | } | 422 | } |
402 | } | 423 | } |
403 | PathKind::Abs => { | 424 | PathKind::Abs => { |
404 | // TODO: absolute use is not supported | 425 | // 2018-style absolute path -- only extern prelude |
405 | return (PerNs::none(), ReachedFixedPoint::Yes); | 426 | let segment = match segments.next() { |
427 | Some((_, segment)) => segment, | ||
428 | None => return (PerNs::none(), ReachedFixedPoint::Yes), | ||
429 | }; | ||
430 | if let Some(def) = self.extern_prelude.get(&segment.name) { | ||
431 | log::debug!("absolute path {:?} resolved to crate {:?}", path, def); | ||
432 | PerNs::types(*def) | ||
433 | } else { | ||
434 | return (PerNs::none(), ReachedFixedPoint::Yes); | ||
435 | } | ||
406 | } | 436 | } |
407 | }); | 437 | }; |
408 | 438 | ||
409 | for (i, segment) in path.segments.iter().enumerate() { | 439 | for (i, segment) in segments { |
410 | let curr = match curr_per_ns.as_ref().take_types() { | 440 | let curr = match curr_per_ns.as_ref().take_types() { |
411 | Some(r) => r, | 441 | Some(r) => r, |
412 | None => { | 442 | None => { |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index db898a782..7e6e48ae0 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -23,6 +23,7 @@ pub(super) struct ImportData { | |||
23 | pub(super) path: Path, | 23 | pub(super) path: Path, |
24 | pub(super) alias: Option<Name>, | 24 | pub(super) alias: Option<Name>, |
25 | pub(super) is_glob: bool, | 25 | pub(super) is_glob: bool, |
26 | pub(super) is_extern_crate: bool, | ||
26 | } | 27 | } |
27 | 28 | ||
28 | /// A set of items and imports declared inside a module, without relation to | 29 | /// A set of items and imports declared inside a module, without relation to |
@@ -199,6 +200,7 @@ impl LoweredModule { | |||
199 | path, | 200 | path, |
200 | alias, | 201 | alias, |
201 | is_glob: false, | 202 | is_glob: false, |
203 | is_extern_crate: true, | ||
202 | }); | 204 | }); |
203 | } | 205 | } |
204 | } | 206 | } |
@@ -228,6 +230,7 @@ impl LoweredModule { | |||
228 | path, | 230 | path, |
229 | alias, | 231 | alias, |
230 | is_glob: segment.is_none(), | 232 | is_glob: segment.is_none(), |
233 | is_extern_crate: false, | ||
231 | }); | 234 | }); |
232 | if let Some(segment) = segment { | 235 | if let Some(segment) = segment { |
233 | source_map.insert(import, segment) | 236 | source_map.insert(import, segment) |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 42c59f76f..0654dbaa1 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -329,7 +329,6 @@ fn item_map_across_crates() { | |||
329 | module.module_id, | 329 | module.module_id, |
330 | " | 330 | " |
331 | Baz: t v | 331 | Baz: t v |
332 | test_crate: t | ||
333 | ", | 332 | ", |
334 | ); | 333 | ); |
335 | } | 334 | } |
@@ -342,7 +341,9 @@ fn extern_crate_rename() { | |||
342 | extern crate alloc as alloc_crate; | 341 | extern crate alloc as alloc_crate; |
343 | 342 | ||
344 | mod alloc; | 343 | mod alloc; |
344 | mod sync; | ||
345 | 345 | ||
346 | //- /sync.rs | ||
346 | use alloc_crate::Arc; | 347 | use alloc_crate::Arc; |
347 | 348 | ||
348 | //- /lib.rs | 349 | //- /lib.rs |
@@ -350,6 +351,7 @@ fn extern_crate_rename() { | |||
350 | ", | 351 | ", |
351 | ); | 352 | ); |
352 | let main_id = sr.files[RelativePath::new("/main.rs")]; | 353 | let main_id = sr.files[RelativePath::new("/main.rs")]; |
354 | let sync_id = sr.files[RelativePath::new("/sync.rs")]; | ||
353 | let lib_id = sr.files[RelativePath::new("/lib.rs")]; | 355 | let lib_id = sr.files[RelativePath::new("/lib.rs")]; |
354 | 356 | ||
355 | let mut crate_graph = CrateGraph::default(); | 357 | let mut crate_graph = CrateGraph::default(); |
@@ -361,7 +363,7 @@ fn extern_crate_rename() { | |||
361 | 363 | ||
362 | db.set_crate_graph(Arc::new(crate_graph)); | 364 | db.set_crate_graph(Arc::new(crate_graph)); |
363 | 365 | ||
364 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 366 | let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); |
365 | let krate = module.krate(&db).unwrap(); | 367 | let krate = module.krate(&db).unwrap(); |
366 | let item_map = db.item_map(krate); | 368 | let item_map = db.item_map(krate); |
367 | 369 | ||
@@ -370,8 +372,6 @@ fn extern_crate_rename() { | |||
370 | module.module_id, | 372 | module.module_id, |
371 | " | 373 | " |
372 | Arc: t v | 374 | Arc: t v |
373 | alloc: t | ||
374 | alloc_crate: t | ||
375 | ", | 375 | ", |
376 | ); | 376 | ); |
377 | } | 377 | } |
@@ -403,8 +403,6 @@ fn import_across_source_roots() { | |||
403 | 403 | ||
404 | let main_id = sr2.files[RelativePath::new("/main.rs")]; | 404 | let main_id = sr2.files[RelativePath::new("/main.rs")]; |
405 | 405 | ||
406 | eprintln!("lib = {:?}, main = {:?}", lib_id, main_id); | ||
407 | |||
408 | let mut crate_graph = CrateGraph::default(); | 406 | let mut crate_graph = CrateGraph::default(); |
409 | let main_crate = crate_graph.add_crate_root(main_id); | 407 | let main_crate = crate_graph.add_crate_root(main_id); |
410 | let lib_crate = crate_graph.add_crate_root(lib_id); | 408 | let lib_crate = crate_graph.add_crate_root(lib_id); |
@@ -423,7 +421,6 @@ fn import_across_source_roots() { | |||
423 | module.module_id, | 421 | module.module_id, |
424 | " | 422 | " |
425 | C: t v | 423 | C: t v |
426 | test_crate: t | ||
427 | ", | 424 | ", |
428 | ); | 425 | ); |
429 | } | 426 | } |
@@ -465,7 +462,6 @@ fn reexport_across_crates() { | |||
465 | module.module_id, | 462 | module.module_id, |
466 | " | 463 | " |
467 | Baz: t v | 464 | Baz: t v |
468 | test_crate: t | ||
469 | ", | 465 | ", |
470 | ); | 466 | ); |
471 | } | 467 | } |