aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/nameres
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r--crates/ra_hir/src/nameres/raw.rs41
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs105
2 files changed, 131 insertions, 15 deletions
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 29aaddbf1..c607b8a11 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -9,7 +9,7 @@ use test_utils::tested_by;
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase}, 11 db::{AstDatabase, DefDatabase},
12 AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, 12 AsName, AstIdMap, Either, FileAstId, HirFileId, ModuleSource, Name, Path, Source,
13}; 13};
14 14
15/// `RawItems` is a set of top-level items in a file (except for impls). 15/// `RawItems` is a set of top-level items in a file (except for impls).
@@ -71,6 +71,8 @@ impl RawItems {
71 raw_items: RawItems::default(), 71 raw_items: RawItems::default(),
72 source_ast_id_map: db.ast_id_map(file_id), 72 source_ast_id_map: db.ast_id_map(file_id),
73 source_map: ImportSourceMap::default(), 73 source_map: ImportSourceMap::default(),
74 file_id,
75 db,
74 }; 76 };
75 if let Some(node) = db.parse_or_expand(file_id) { 77 if let Some(node) = db.parse_or_expand(file_id) {
76 if let Some(source_file) = ast::SourceFile::cast(node.clone()) { 78 if let Some(source_file) = ast::SourceFile::cast(node.clone()) {
@@ -192,13 +194,15 @@ pub(super) struct MacroData {
192 pub(super) export: bool, 194 pub(super) export: bool,
193} 195}
194 196
195struct RawItemsCollector { 197struct RawItemsCollector<DB> {
196 raw_items: RawItems, 198 raw_items: RawItems,
197 source_ast_id_map: Arc<AstIdMap>, 199 source_ast_id_map: Arc<AstIdMap>,
198 source_map: ImportSourceMap, 200 source_map: ImportSourceMap,
201 file_id: HirFileId,
202 db: DB,
199} 203}
200 204
201impl RawItemsCollector { 205impl<DB: AstDatabase> RawItemsCollector<&'_ DB> {
202 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) { 206 fn process_module(&mut self, current_module: Option<Module>, body: impl ast::ModuleItemOwner) {
203 for item_or_macro in body.items_with_macros() { 207 for item_or_macro in body.items_with_macros() {
204 match item_or_macro { 208 match item_or_macro {
@@ -300,17 +304,21 @@ impl RawItemsCollector {
300 fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) { 304 fn add_use_item(&mut self, current_module: Option<Module>, use_item: ast::UseItem) {
301 let is_prelude = use_item.has_atom_attr("prelude_import"); 305 let is_prelude = use_item.has_atom_attr("prelude_import");
302 306
303 Path::expand_use_item(&use_item, |path, use_tree, is_glob, alias| { 307 Path::expand_use_item(
304 let import_data = ImportData { 308 Source { ast: use_item, file_id: self.file_id },
305 path, 309 self.db,
306 alias, 310 |path, use_tree, is_glob, alias| {
307 is_glob, 311 let import_data = ImportData {
308 is_prelude, 312 path,
309 is_extern_crate: false, 313 alias,
310 is_macro_use: false, 314 is_glob,
311 }; 315 is_prelude,
312 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree))); 316 is_extern_crate: false,
313 }) 317 is_macro_use: false,
318 };
319 self.push_import(current_module, import_data, Either::A(AstPtr::new(use_tree)));
320 },
321 )
314 } 322 }
315 323
316 fn add_extern_crate_item( 324 fn add_extern_crate_item(
@@ -335,7 +343,10 @@ impl RawItemsCollector {
335 } 343 }
336 344
337 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) { 345 fn add_macro(&mut self, current_module: Option<Module>, m: ast::MacroCall) {
338 let path = match m.path().and_then(Path::from_ast) { 346 let path = match m
347 .path()
348 .and_then(|path| Path::from_src(Source { ast: path, file_id: self.file_id }, self.db))
349 {
339 Some(it) => it, 350 Some(it) => it,
340 _ => return, 351 _ => return,
341 }; 352 };
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index bd60f4258..e4b408394 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -515,3 +515,108 @@ fn path_qualified_macros() {
515 ⋮not_found: _ 515 ⋮not_found: _
516 "###); 516 "###);
517} 517}
518
519#[test]
520fn macro_dollar_crate_is_correct_in_item() {
521 covers!(macro_dollar_crate_self);
522 covers!(macro_dollar_crate_other);
523 let map = def_map_with_crate_graph(
524 "
525 //- /main.rs
526 #[macro_use]
527 extern crate foo;
528
529 #[macro_use]
530 mod m {
531 macro_rules! current {
532 () => {
533 use $crate::Foo as FooSelf;
534 }
535 }
536 }
537
538 struct Foo;
539
540 current!();
541 not_current1!();
542 foo::not_current2!();
543
544 //- /lib.rs
545 mod m {
546 #[macro_export]
547 macro_rules! not_current1 {
548 () => {
549 use $crate::Bar;
550 }
551 }
552 }
553
554 #[macro_export]
555 macro_rules! not_current2 {
556 () => {
557 use $crate::Baz;
558 }
559 }
560
561 struct Bar;
562 struct Baz;
563 ",
564 crate_graph! {
565 "main": ("/main.rs", ["foo"]),
566 "foo": ("/lib.rs", []),
567 },
568 );
569 assert_snapshot!(map, @r###"
570 ⋮crate
571 ⋮Bar: t v
572 ⋮Baz: t v
573 ⋮Foo: t v
574 ⋮FooSelf: t v
575 ⋮foo: t
576 ⋮m: t
577
578 ⋮crate::m
579 "###);
580}
581
582#[test]
583fn macro_dollar_crate_is_correct_in_indirect_deps() {
584 covers!(macro_dollar_crate_other);
585 // From std
586 let map = def_map_with_crate_graph(
587 r#"
588 //- /main.rs
589 foo!();
590
591 //- /std.rs
592 #[prelude_import]
593 use self::prelude::*;
594
595 pub use core::foo;
596
597 mod prelude {}
598
599 #[macro_use]
600 mod std_macros;
601
602 //- /core.rs
603 #[macro_export]
604 macro_rules! foo {
605 () => {
606 use $crate::bar;
607 }
608 }
609
610 pub struct bar;
611 "#,
612 crate_graph! {
613 "main": ("/main.rs", ["std"]),
614 "std": ("/std.rs", ["core"]),
615 "core": ("/core.rs", []),
616 },
617 );
618 assert_snapshot!(map, @r###"
619 ⋮crate
620 ⋮bar: t v
621 "###);
622}