aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-13 20:14:39 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-13 20:14:39 +0000
commitcb4327b3a9f0858235dc20b7c5c7e25c6c330aab (patch)
tree489b3497b2762dcabf60d2674031585431e16959 /crates/ra_hir/src/nameres
parent65266c644a31e6b321e5afb3c5a2ee75be76cb0c (diff)
parent911e32bca9b73e66eceb6bbee3768c82e94597d5 (diff)
Merge #816
816: Prelude & Edition 2015 import resolution r=matklad a=flodiebold I implemented the prelude import, but it turned out to be useless without being able to resolve any of the imports in the prelude :sweat_smile: So I had to add some edition handling and handle 2015-style imports (at least the simplified scheme proposed in rust-lang/rust#57745). So now finally `Option` resolves :smile: One remaining problem is that we don't actually know the edition for sysroot crates. They're currently hardcoded to 2015, but there's already a bunch of PRs upgrading the editions of various rustc crates, so we'll have to detect the edition somehow, or just change the hardcoding to 2018 later, I guess... ~Also currently missing is completion for prelude names, though that shouldn't be hard to add. And `Vec` still doesn't resolve, so I need to look into that.~ Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/lower.rs16
-rw-r--r--crates/ra_hir/src/nameres/tests.rs112
2 files changed, 120 insertions, 8 deletions
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs
index 3cd496d7f..81d80654c 100644
--- a/crates/ra_hir/src/nameres/lower.rs
+++ b/crates/ra_hir/src/nameres/lower.rs
@@ -2,13 +2,13 @@ use std::sync::Arc;
2 2
3use ra_syntax::{ 3use ra_syntax::{
4 AstNode, SourceFile, TreeArc, AstPtr, 4 AstNode, SourceFile, TreeArc, AstPtr,
5 ast::{self, ModuleItemOwner, NameOwner}, 5 ast::{self, ModuleItemOwner, NameOwner, AttrsOwner},
6}; 6};
7use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 7use 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,
@@ -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_prelude: bool,
26 pub(super) is_extern_crate: bool, 27 pub(super) is_extern_crate: bool,
27} 28}
28 29
@@ -179,18 +180,14 @@ impl LoweredModule {
179 self.add_use_item(source_map, it); 180 self.add_use_item(source_map, it);
180 } 181 }
181 ast::ModuleItemKind::ExternCrateItem(it) => { 182 ast::ModuleItemKind::ExternCrateItem(it) => {
182 // Lower `extern crate x` to `use ::x`. This is kind of cheating
183 // and only works if we always interpret absolute paths in the
184 // 2018 style; otherwise `::x` could also refer to a module in
185 // the crate root.
186 if let Some(name_ref) = it.name_ref() { 183 if let Some(name_ref) = it.name_ref() {
187 let mut path = Path::from_name_ref(name_ref); 184 let path = Path::from_name_ref(name_ref);
188 path.kind = PathKind::Abs;
189 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);
190 self.imports.alloc(ImportData { 186 self.imports.alloc(ImportData {
191 path, 187 path,
192 alias, 188 alias,
193 is_glob: false, 189 is_glob: false,
190 is_prelude: false,
194 is_extern_crate: true, 191 is_extern_crate: true,
195 }); 192 });
196 } 193 }
@@ -214,11 +211,14 @@ impl LoweredModule {
214 } 211 }
215 212
216 fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { 213 fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) {
214 let is_prelude =
215 item.attrs().any(|attr| attr.as_atom().map(|s| s == "prelude_import").unwrap_or(false));
217 Path::expand_use_item(item, |path, segment, alias| { 216 Path::expand_use_item(item, |path, segment, alias| {
218 let import = self.imports.alloc(ImportData { 217 let import = self.imports.alloc(ImportData {
219 path, 218 path,
220 alias, 219 alias,
221 is_glob: segment.is_none(), 220 is_glob: segment.is_none(),
221 is_prelude,
222 is_extern_crate: false, 222 is_extern_crate: false,
223 }); 223 });
224 if let Some(segment) = segment { 224 if let Some(segment) = segment {
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 6dbe759d1..6402c89c0 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -266,6 +266,45 @@ fn glob_across_crates() {
266} 266}
267 267
268#[test] 268#[test]
269fn edition_2015_imports() {
270 let mut db = MockDatabase::with_files(
271 "
272 //- /main.rs
273 mod foo;
274 mod bar;
275
276 //- /bar.rs
277 struct Bar;
278
279 //- /foo.rs
280 use bar::Bar;
281 use other_crate::FromLib;
282
283 //- /lib.rs
284 struct FromLib;
285 ",
286 );
287 db.set_crate_graph_from_fixture(crate_graph! {
288 "main": ("/main.rs", "2015", ["other_crate"]),
289 "other_crate": ("/lib.rs", "2018", []),
290 });
291 let foo_id = db.file_id_of("/foo.rs");
292
293 let module = crate::source_binder::module_from_file_id(&db, foo_id).unwrap();
294 let krate = module.krate(&db).unwrap();
295 let item_map = db.item_map(krate);
296
297 check_module_item_map(
298 &item_map,
299 module.module_id,
300 "
301 Bar: t v
302 FromLib: t v
303 ",
304 );
305}
306
307#[test]
269fn module_resolution_works_for_non_standard_filenames() { 308fn module_resolution_works_for_non_standard_filenames() {
270 let mut db = MockDatabase::with_files( 309 let mut db = MockDatabase::with_files(
271 " 310 "
@@ -297,6 +336,43 @@ fn module_resolution_works_for_non_standard_filenames() {
297} 336}
298 337
299#[test] 338#[test]
339fn std_prelude() {
340 covers!(std_prelude);
341 let mut db = MockDatabase::with_files(
342 "
343 //- /main.rs
344 use Foo::*;
345
346 //- /lib.rs
347 mod prelude;
348 #[prelude_import]
349 use prelude::*;
350
351 //- /prelude.rs
352 pub enum Foo { Bar, Baz };
353 ",
354 );
355 db.set_crate_graph_from_fixture(crate_graph! {
356 "main": ("/main.rs", ["test_crate"]),
357 "test_crate": ("/lib.rs", []),
358 });
359 let main_id = db.file_id_of("/main.rs");
360
361 let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap();
362 let krate = module.krate(&db).unwrap();
363 let item_map = db.item_map(krate);
364
365 check_module_item_map(
366 &item_map,
367 module.module_id,
368 "
369 Bar: t v
370 Baz: t v
371 ",
372 );
373}
374
375#[test]
300fn name_res_works_for_broken_modules() { 376fn name_res_works_for_broken_modules() {
301 covers!(name_res_works_for_broken_modules); 377 covers!(name_res_works_for_broken_modules);
302 let (item_map, module_id) = item_map( 378 let (item_map, module_id) = item_map(
@@ -467,6 +543,42 @@ fn extern_crate_rename() {
467} 543}
468 544
469#[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]
470fn import_across_source_roots() { 582fn import_across_source_roots() {
471 let mut db = MockDatabase::with_files( 583 let mut db = MockDatabase::with_files(
472 " 584 "