aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-02-13 19:42:43 +0000
committerFlorian Diebold <[email protected]>2019-02-13 20:13:08 +0000
commit92c595a6a6f7624092432d28ffd7e0ffd189cbda (patch)
treea4a697b02219c22d4be726cf05e68dfb4ba2b108
parent70839b7ef8217fd019ce5bd3a643a8a16f5fa829 (diff)
Handle extern crates better, so they work correctly in 2015 edition
(see the removed comment.)
-rw-r--r--crates/ra_hir/src/nameres.rs25
-rw-r--r--crates/ra_hir/src/nameres/lower.rs9
-rw-r--r--crates/ra_hir/src/nameres/tests.rs36
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};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9 9
10use crate::{ 10use 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]
546fn 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]
546fn import_across_source_roots() { 582fn import_across_source_roots() {
547 let mut db = MockDatabase::with_files( 583 let mut db = MockDatabase::with_files(
548 " 584 "