diff options
Diffstat (limited to 'crates/ra_hir/src/nameres')
-rw-r--r-- | crates/ra_hir/src/nameres/raw.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir/src/nameres/tests/macros.rs | 105 |
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 | ||
10 | use crate::{ | 10 | use 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 | ||
195 | struct RawItemsCollector { | 197 | struct 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 | ||
201 | impl RawItemsCollector { | 205 | impl<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] | ||
520 | fn 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] | ||
583 | fn 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 | } | ||