diff options
author | Florian Diebold <[email protected]> | 2019-02-13 19:42:43 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2019-02-13 20:13:08 +0000 |
commit | 92c595a6a6f7624092432d28ffd7e0ffd189cbda (patch) | |
tree | a4a697b02219c22d4be726cf05e68dfb4ba2b108 /crates/ra_hir/src | |
parent | 70839b7ef8217fd019ce5bd3a643a8a16f5fa829 (diff) |
Handle extern crates better, so they work correctly in 2015 edition
(see the removed comment.)
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/nameres.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/lower.rs | 9 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests.rs | 36 |
3 files changed, 55 insertions, 15 deletions
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 028e2bee3..cd7b41cff 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -287,12 +287,18 @@ where | |||
287 | ) -> ReachedFixedPoint { | 287 | ) -> ReachedFixedPoint { |
288 | log::debug!("resolving import: {:?} ({:?})", import, self.result.edition); | 288 | log::debug!("resolving import: {:?} ({:?})", import, self.result.edition); |
289 | let original_module = Module { krate: self.krate, module_id }; | 289 | let original_module = Module { krate: self.krate, module_id }; |
290 | let (def, reached_fixedpoint) = self.result.resolve_path_fp( | 290 | |
291 | self.db, | 291 | let (def, reached_fixedpoint) = if import.is_extern_crate { |
292 | ResolveMode::Import, | 292 | let res = self.result.resolve_name_in_extern_prelude( |
293 | original_module, | 293 | &import |
294 | &import.path, | 294 | .path |
295 | ); | 295 | .as_ident() |
296 | .expect("extern crate should have been desugared to one-element path"), | ||
297 | ); | ||
298 | (res, if res.is_none() { ReachedFixedPoint::No } else { ReachedFixedPoint::Yes }) | ||
299 | } else { | ||
300 | self.result.resolve_path_fp(self.db, ResolveMode::Import, original_module, &import.path) | ||
301 | }; | ||
296 | 302 | ||
297 | if reached_fixedpoint != ReachedFixedPoint::Yes { | 303 | if reached_fixedpoint != ReachedFixedPoint::Yes { |
298 | return reached_fixedpoint; | 304 | return reached_fixedpoint; |
@@ -502,6 +508,10 @@ impl ItemMap { | |||
502 | from_scope.or(from_extern_prelude).or(from_prelude) | 508 | from_scope.or(from_extern_prelude).or(from_prelude) |
503 | } | 509 | } |
504 | 510 | ||
511 | fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs<ModuleDef> { | ||
512 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)) | ||
513 | } | ||
514 | |||
505 | fn resolve_name_in_crate_root_or_extern_prelude( | 515 | fn resolve_name_in_crate_root_or_extern_prelude( |
506 | &self, | 516 | &self, |
507 | db: &impl PersistentHirDatabase, | 517 | db: &impl PersistentHirDatabase, |
@@ -511,8 +521,7 @@ impl ItemMap { | |||
511 | let crate_root = module.crate_root(db); | 521 | let crate_root = module.crate_root(db); |
512 | let from_crate_root = | 522 | let from_crate_root = |
513 | self[crate_root.module_id].items.get(name).map_or(PerNs::none(), |it| it.def); | 523 | self[crate_root.module_id].items.get(name).map_or(PerNs::none(), |it| it.def); |
514 | let from_extern_prelude = | 524 | let from_extern_prelude = self.resolve_name_in_extern_prelude(name); |
515 | self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); | ||
516 | 525 | ||
517 | from_crate_root.or(from_extern_prelude) | 526 | from_crate_root.or(from_extern_prelude) |
518 | } | 527 | } |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 922dbe9c1..81d80654c 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -8,7 +8,7 @@ use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | SourceItemId, Path, PathKind, ModuleSource, Name, | 11 | SourceItemId, Path, ModuleSource, Name, |
12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, |
13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, | 13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, |
14 | ids::LocationCtx, PersistentHirDatabase, | 14 | ids::LocationCtx, PersistentHirDatabase, |
@@ -180,13 +180,8 @@ impl LoweredModule { | |||
180 | self.add_use_item(source_map, it); | 180 | self.add_use_item(source_map, it); |
181 | } | 181 | } |
182 | ast::ModuleItemKind::ExternCrateItem(it) => { | 182 | ast::ModuleItemKind::ExternCrateItem(it) => { |
183 | // Lower `extern crate x` to `use ::x`. This is kind of cheating | ||
184 | // and only works if we always interpret absolute paths in the | ||
185 | // 2018 style; otherwise `::x` could also refer to a module in | ||
186 | // the crate root. | ||
187 | if let Some(name_ref) = it.name_ref() { | 183 | if let Some(name_ref) = it.name_ref() { |
188 | let mut path = Path::from_name_ref(name_ref); | 184 | let path = Path::from_name_ref(name_ref); |
189 | path.kind = PathKind::Abs; | ||
190 | let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name); | 185 | let alias = it.alias().and_then(|a| a.name()).map(AsName::as_name); |
191 | self.imports.alloc(ImportData { | 186 | self.imports.alloc(ImportData { |
192 | path, | 187 | path, |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index e764e0855..6402c89c0 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -543,6 +543,42 @@ fn extern_crate_rename() { | |||
543 | } | 543 | } |
544 | 544 | ||
545 | #[test] | 545 | #[test] |
546 | fn extern_crate_rename_2015_edition() { | ||
547 | let mut db = MockDatabase::with_files( | ||
548 | " | ||
549 | //- /main.rs | ||
550 | extern crate alloc as alloc_crate; | ||
551 | |||
552 | mod alloc; | ||
553 | mod sync; | ||
554 | |||
555 | //- /sync.rs | ||
556 | use alloc_crate::Arc; | ||
557 | |||
558 | //- /lib.rs | ||
559 | struct Arc; | ||
560 | ", | ||
561 | ); | ||
562 | db.set_crate_graph_from_fixture(crate_graph! { | ||
563 | "main": ("/main.rs", "2015", ["alloc"]), | ||
564 | "alloc": ("/lib.rs", []), | ||
565 | }); | ||
566 | let sync_id = db.file_id_of("/sync.rs"); | ||
567 | |||
568 | let module = crate::source_binder::module_from_file_id(&db, sync_id).unwrap(); | ||
569 | let krate = module.krate(&db).unwrap(); | ||
570 | let item_map = db.item_map(krate); | ||
571 | |||
572 | check_module_item_map( | ||
573 | &item_map, | ||
574 | module.module_id, | ||
575 | " | ||
576 | Arc: t v | ||
577 | ", | ||
578 | ); | ||
579 | } | ||
580 | |||
581 | #[test] | ||
546 | fn import_across_source_roots() { | 582 | fn import_across_source_roots() { |
547 | let mut db = MockDatabase::with_files( | 583 | let mut db = MockDatabase::with_files( |
548 | " | 584 | " |