aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/find_path.rs249
-rw-r--r--crates/hir_def/src/import_map.rs46
-rw-r--r--crates/hir_def/src/nameres.rs2
-rw-r--r--crates/hir_def/src/nameres/collector.rs3
-rw-r--r--crates/hir_def/src/nameres/tests/macros.rs7
-rw-r--r--crates/hir_def/src/path.rs22
6 files changed, 182 insertions, 147 deletions
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index baf374144..02613c4c4 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -19,12 +19,17 @@ use crate::{
19/// *from where* you're referring to the item, hence the `from` parameter. 19/// *from where* you're referring to the item, hence the `from` parameter.
20pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 20pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
21 let _p = profile::span("find_path"); 21 let _p = profile::span("find_path");
22 find_path_inner(db, item, from, MAX_PATH_LEN, Prefixed::Not) 22 find_path_inner(db, item, from, MAX_PATH_LEN, None)
23} 23}
24 24
25pub fn find_path_prefixed(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> { 25pub fn find_path_prefixed(
26 let _p = profile::span("find_path_absolute"); 26 db: &dyn DefDatabase,
27 find_path_inner(db, item, from, MAX_PATH_LEN, Prefixed::Plain) 27 item: ItemInNs,
28 from: ModuleId,
29 prefix_kind: PrefixKind,
30) -> Option<ModPath> {
31 let _p = profile::span("find_path_prefixed");
32 find_path_inner(db, item, from, MAX_PATH_LEN, Some(prefix_kind))
28} 33}
29 34
30const MAX_PATH_LEN: usize = 15; 35const MAX_PATH_LEN: usize = 15;
@@ -42,58 +47,52 @@ impl ModPath {
42 } 47 }
43} 48}
44 49
45fn check_crate_self_super( 50fn check_self_super(def_map: &CrateDefMap, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
46 def_map: &CrateDefMap, 51 if item == ItemInNs::Types(from.into()) {
47 item: ItemInNs,
48 from: ModuleId,
49) -> Option<ModPath> {
50 // - if the item is the crate root, return `crate`
51 if item
52 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId {
53 krate: from.krate,
54 local_id: def_map.root,
55 }))
56 {
57 Some(ModPath::from_segments(PathKind::Crate, Vec::new()))
58 } else if item == ItemInNs::Types(from.into()) {
59 // - if the item is the module we're in, use `self` 52 // - if the item is the module we're in, use `self`
60 Some(ModPath::from_segments(PathKind::Super(0), Vec::new())) 53 Some(ModPath::from_segments(PathKind::Super(0), Vec::new()))
61 } else { 54 } else if let Some(parent_id) = def_map.modules[from.local_id].parent {
62 if let Some(parent_id) = def_map.modules[from.local_id].parent { 55 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly)
63 // - if the item is the parent module, use `super` (this is not used recursively, since `super::super` is ugly) 56 if item
64 if item 57 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId {
65 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId { 58 krate: from.krate,
66 krate: from.krate, 59 local_id: parent_id,
67 local_id: parent_id, 60 }))
68 })) 61 {
69 { 62 Some(ModPath::from_segments(PathKind::Super(1), Vec::new()))
70 return Some(ModPath::from_segments(PathKind::Super(1), Vec::new())); 63 } else {
71 } 64 None
72 } 65 }
66 } else {
73 None 67 None
74 } 68 }
75} 69}
76 70
77#[derive(Copy, Clone, PartialEq, Eq)] 71#[derive(Copy, Clone, Debug, PartialEq, Eq)]
78pub enum Prefixed { 72pub enum PrefixKind {
79 Not, 73 /// Causes paths to always start with either `self`, `super`, `crate` or a crate-name.
74 /// This is the same as plain, just that paths will start with `self` iprepended f the path
75 /// starts with an identifier that is not a crate.
80 BySelf, 76 BySelf,
77 /// Causes paths to ignore imports in the local module.
81 Plain, 78 Plain,
79 /// Causes paths to start with `crate` where applicable, effectively forcing paths to be absolute.
80 ByCrate,
82} 81}
83 82
84impl Prefixed { 83impl PrefixKind {
85 #[inline] 84 #[inline]
86 fn prefix(self) -> Option<PathKind> { 85 fn prefix(self) -> PathKind {
87 match self { 86 match self {
88 Prefixed::Not => None, 87 PrefixKind::BySelf => PathKind::Super(0),
89 Prefixed::BySelf => Some(PathKind::Super(0)), 88 PrefixKind::Plain => PathKind::Plain,
90 Prefixed::Plain => Some(PathKind::Plain), 89 PrefixKind::ByCrate => PathKind::Crate,
91 } 90 }
92 } 91 }
93 92
94 #[inline] 93 #[inline]
95 fn prefixed(self) -> bool { 94 fn is_absolute(&self) -> bool {
96 self != Prefixed::Not 95 self == &PrefixKind::ByCrate
97 } 96 }
98} 97}
99 98
@@ -102,7 +101,7 @@ fn find_path_inner(
102 item: ItemInNs, 101 item: ItemInNs,
103 from: ModuleId, 102 from: ModuleId,
104 max_len: usize, 103 max_len: usize,
105 prefixed: Prefixed, 104 prefixed: Option<PrefixKind>,
106) -> Option<ModPath> { 105) -> Option<ModPath> {
107 if max_len == 0 { 106 if max_len == 0 {
108 return None; 107 return None;
@@ -115,13 +114,25 @@ fn find_path_inner(
115 let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope; 114 let from_scope: &crate::item_scope::ItemScope = &def_map.modules[from.local_id].scope;
116 let scope_name = 115 let scope_name =
117 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None }; 116 if let Some((name, _)) = from_scope.name_of(item) { Some(name.clone()) } else { None };
118 if !prefixed.prefixed() && scope_name.is_some() { 117 if prefixed.is_none() && scope_name.is_some() {
119 return scope_name 118 return scope_name
120 .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name])); 119 .map(|scope_name| ModPath::from_segments(PathKind::Plain, vec![scope_name]));
121 } 120 }
122 121
123 if let modpath @ Some(_) = check_crate_self_super(&def_map, item, from) { 122 // - if the item is the crate root, return `crate`
124 return modpath; 123 if item
124 == ItemInNs::Types(ModuleDefId::ModuleId(ModuleId {
125 krate: from.krate,
126 local_id: def_map.root,
127 }))
128 {
129 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
130 }
131
132 if prefixed.filter(PrefixKind::is_absolute).is_none() {
133 if let modpath @ Some(_) = check_self_super(&def_map, item, from) {
134 return modpath;
135 }
125 } 136 }
126 137
127 // - if the item is the crate root of a dependency crate, return the name from the extern prelude 138 // - if the item is the crate root of a dependency crate, return the name from the extern prelude
@@ -211,6 +222,7 @@ fn find_path_inner(
211 best_path_len - 1, 222 best_path_len - 1,
212 prefixed, 223 prefixed,
213 )?; 224 )?;
225 mark::hit!(partially_imported);
214 path.segments.push(info.path.segments.last().unwrap().clone()); 226 path.segments.push(info.path.segments.last().unwrap().clone());
215 Some(path) 227 Some(path)
216 }) 228 })
@@ -226,7 +238,7 @@ fn find_path_inner(
226 } 238 }
227 } 239 }
228 240
229 if let Some(prefix) = prefixed.prefix() { 241 if let Some(prefix) = prefixed.map(PrefixKind::prefix) {
230 best_path.or_else(|| { 242 best_path.or_else(|| {
231 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) 243 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name]))
232 }) 244 })
@@ -355,7 +367,7 @@ mod tests {
355 /// `code` needs to contain a cursor marker; checks that `find_path` for the 367 /// `code` needs to contain a cursor marker; checks that `find_path` for the
356 /// item the `path` refers to returns that same path when called from the 368 /// item the `path` refers to returns that same path when called from the
357 /// module the cursor is in. 369 /// module the cursor is in.
358 fn check_found_path_(ra_fixture: &str, path: &str, absolute: bool) { 370 fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) {
359 let (db, pos) = TestDB::with_position(ra_fixture); 371 let (db, pos) = TestDB::with_position(ra_fixture);
360 let module = db.module_for_file(pos.file_id); 372 let module = db.module_for_file(pos.file_id);
361 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path)); 373 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
@@ -375,20 +387,22 @@ mod tests {
375 .take_types() 387 .take_types()
376 .unwrap(); 388 .unwrap();
377 389
378 let found_path = if absolute { find_path_prefixed } else { find_path }( 390 let found_path =
379 &db, 391 find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind);
380 ItemInNs::Types(resolved), 392 assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind);
381 module,
382 );
383 assert_eq!(found_path, Some(mod_path), "absolute {}", absolute);
384 } 393 }
385 394
386 fn check_found_path(ra_fixture: &str, path: &str) { 395 fn check_found_path(
387 check_found_path_(ra_fixture, path, false); 396 ra_fixture: &str,
388 } 397 unprefixed: &str,
389 398 prefixed: &str,
390 fn check_found_path_abs(ra_fixture: &str, path: &str) { 399 absolute: &str,
391 check_found_path_(ra_fixture, path, true); 400 self_prefixed: &str,
401 ) {
402 check_found_path_(ra_fixture, unprefixed, None);
403 check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain));
404 check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate));
405 check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf));
392 } 406 }
393 407
394 #[test] 408 #[test]
@@ -398,8 +412,7 @@ mod tests {
398 struct S; 412 struct S;
399 <|> 413 <|>
400 "#; 414 "#;
401 check_found_path(code, "S"); 415 check_found_path(code, "S", "S", "crate::S", "self::S");
402 check_found_path_abs(code, "S");
403 } 416 }
404 417
405 #[test] 418 #[test]
@@ -409,8 +422,7 @@ mod tests {
409 enum E { A } 422 enum E { A }
410 <|> 423 <|>
411 "#; 424 "#;
412 check_found_path(code, "E::A"); 425 check_found_path(code, "E::A", "E::A", "E::A", "E::A");
413 check_found_path_abs(code, "E::A");
414 } 426 }
415 427
416 #[test] 428 #[test]
@@ -422,8 +434,7 @@ mod tests {
422 } 434 }
423 <|> 435 <|>
424 "#; 436 "#;
425 check_found_path(code, "foo::S"); 437 check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S");
426 check_found_path_abs(code, "foo::S");
427 } 438 }
428 439
429 #[test] 440 #[test]
@@ -437,8 +448,7 @@ mod tests {
437 //- /foo/bar.rs 448 //- /foo/bar.rs
438 <|> 449 <|>
439 "#; 450 "#;
440 check_found_path(code, "super::S"); 451 check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S");
441 check_found_path_abs(code, "super::S");
442 } 452 }
443 453
444 #[test] 454 #[test]
@@ -449,8 +459,7 @@ mod tests {
449 //- /foo.rs 459 //- /foo.rs
450 <|> 460 <|>
451 "#; 461 "#;
452 check_found_path(code, "self"); 462 check_found_path(code, "self", "self", "crate::foo", "self");
453 check_found_path_abs(code, "self");
454 } 463 }
455 464
456 #[test] 465 #[test]
@@ -461,8 +470,7 @@ mod tests {
461 //- /foo.rs 470 //- /foo.rs
462 <|> 471 <|>
463 "#; 472 "#;
464 check_found_path(code, "crate"); 473 check_found_path(code, "crate", "crate", "crate", "crate");
465 check_found_path_abs(code, "crate");
466 } 474 }
467 475
468 #[test] 476 #[test]
@@ -474,8 +482,7 @@ mod tests {
474 //- /foo.rs 482 //- /foo.rs
475 <|> 483 <|>
476 "#; 484 "#;
477 check_found_path(code, "crate::S"); 485 check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S");
478 check_found_path_abs(code, "crate::S");
479 } 486 }
480 487
481 #[test] 488 #[test]
@@ -486,8 +493,7 @@ mod tests {
486 //- /std.rs crate:std 493 //- /std.rs crate:std
487 pub struct S; 494 pub struct S;
488 "#; 495 "#;
489 check_found_path(code, "std::S"); 496 check_found_path(code, "std::S", "std::S", "std::S", "std::S");
490 check_found_path_abs(code, "std::S");
491 } 497 }
492 498
493 #[test] 499 #[test]
@@ -499,12 +505,18 @@ mod tests {
499 //- /std.rs crate:std 505 //- /std.rs crate:std
500 pub struct S; 506 pub struct S;
501 "#; 507 "#;
502 check_found_path(code, "std_renamed::S"); 508 check_found_path(
503 check_found_path_abs(code, "std_renamed::S"); 509 code,
510 "std_renamed::S",
511 "std_renamed::S",
512 "std_renamed::S",
513 "std_renamed::S",
514 );
504 } 515 }
505 516
506 #[test] 517 #[test]
507 fn partially_imported() { 518 fn partially_imported() {
519 mark::check!(partially_imported);
508 // Tests that short paths are used even for external items, when parts of the path are 520 // Tests that short paths are used even for external items, when parts of the path are
509 // already in scope. 521 // already in scope.
510 let code = r#" 522 let code = r#"
@@ -520,8 +532,13 @@ mod tests {
520 } 532 }
521 } 533 }
522 "#; 534 "#;
523 check_found_path(code, "ast::ModuleItem"); 535 check_found_path(
524 check_found_path_abs(code, "syntax::ast::ModuleItem"); 536 code,
537 "ast::ModuleItem",
538 "syntax::ast::ModuleItem",
539 "syntax::ast::ModuleItem",
540 "syntax::ast::ModuleItem",
541 );
525 542
526 let code = r#" 543 let code = r#"
527 //- /main.rs crate:main deps:syntax 544 //- /main.rs crate:main deps:syntax
@@ -535,8 +552,13 @@ mod tests {
535 } 552 }
536 } 553 }
537 "#; 554 "#;
538 check_found_path(code, "syntax::ast::ModuleItem"); 555 check_found_path(
539 check_found_path_abs(code, "syntax::ast::ModuleItem"); 556 code,
557 "syntax::ast::ModuleItem",
558 "syntax::ast::ModuleItem",
559 "syntax::ast::ModuleItem",
560 "syntax::ast::ModuleItem",
561 );
540 } 562 }
541 563
542 #[test] 564 #[test]
@@ -549,8 +571,7 @@ mod tests {
549 } 571 }
550 <|> 572 <|>
551 "#; 573 "#;
552 check_found_path(code, "bar::S"); 574 check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S");
553 check_found_path_abs(code, "bar::S");
554 } 575 }
555 576
556 #[test] 577 #[test]
@@ -563,8 +584,7 @@ mod tests {
563 } 584 }
564 <|> 585 <|>
565 "#; 586 "#;
566 check_found_path(code, "bar::U"); 587 check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U");
567 check_found_path_abs(code, "bar::U");
568 } 588 }
569 589
570 #[test] 590 #[test]
@@ -577,8 +597,7 @@ mod tests {
577 //- /core.rs crate:core 597 //- /core.rs crate:core
578 pub struct S; 598 pub struct S;
579 "#; 599 "#;
580 check_found_path(code, "std::S"); 600 check_found_path(code, "std::S", "std::S", "std::S", "std::S");
581 check_found_path_abs(code, "std::S");
582 } 601 }
583 602
584 #[test] 603 #[test]
@@ -591,8 +610,7 @@ mod tests {
591 #[prelude_import] 610 #[prelude_import]
592 pub use prelude::*; 611 pub use prelude::*;
593 "#; 612 "#;
594 check_found_path(code, "S"); 613 check_found_path(code, "S", "S", "S", "S");
595 check_found_path_abs(code, "S");
596 } 614 }
597 615
598 #[test] 616 #[test]
@@ -608,10 +626,8 @@ mod tests {
608 #[prelude_import] 626 #[prelude_import]
609 pub use prelude::*; 627 pub use prelude::*;
610 "#; 628 "#;
611 check_found_path(code, "None"); 629 check_found_path(code, "None", "None", "None", "None");
612 check_found_path(code, "Some"); 630 check_found_path(code, "Some", "Some", "Some", "Some");
613 check_found_path_abs(code, "None");
614 check_found_path_abs(code, "Some");
615 } 631 }
616 632
617 #[test] 633 #[test]
@@ -627,8 +643,7 @@ mod tests {
627 //- /baz.rs 643 //- /baz.rs
628 pub use crate::foo::bar::S; 644 pub use crate::foo::bar::S;
629 "#; 645 "#;
630 check_found_path(code, "baz::S"); 646 check_found_path(code, "baz::S", "baz::S", "crate::baz::S", "self::baz::S");
631 check_found_path_abs(code, "baz::S");
632 } 647 }
633 648
634 #[test] 649 #[test]
@@ -642,8 +657,7 @@ mod tests {
642 <|> 657 <|>
643 "#; 658 "#;
644 // crate::S would be shorter, but using private imports seems wrong 659 // crate::S would be shorter, but using private imports seems wrong
645 check_found_path(code, "crate::bar::S"); 660 check_found_path(code, "crate::bar::S", "crate::bar::S", "crate::bar::S", "crate::bar::S");
646 check_found_path_abs(code, "crate::bar::S");
647 } 661 }
648 662
649 #[test] 663 #[test]
@@ -661,8 +675,7 @@ mod tests {
661 //- /baz.rs 675 //- /baz.rs
662 pub use super::foo; 676 pub use super::foo;
663 "#; 677 "#;
664 check_found_path(code, "crate::foo::S"); 678 check_found_path(code, "crate::foo::S", "crate::foo::S", "crate::foo::S", "crate::foo::S");
665 check_found_path_abs(code, "crate::foo::S");
666 } 679 }
667 680
668 #[test] 681 #[test]
@@ -682,8 +695,13 @@ mod tests {
682 pub struct Arc; 695 pub struct Arc;
683 } 696 }
684 "#; 697 "#;
685 check_found_path(code, "std::sync::Arc"); 698 check_found_path(
686 check_found_path_abs(code, "std::sync::Arc"); 699 code,
700 "std::sync::Arc",
701 "std::sync::Arc",
702 "std::sync::Arc",
703 "std::sync::Arc",
704 );
687 } 705 }
688 706
689 #[test] 707 #[test]
@@ -707,8 +725,13 @@ mod tests {
707 pub struct Error; 725 pub struct Error;
708 } 726 }
709 "#; 727 "#;
710 check_found_path(code, "core::fmt::Error"); 728 check_found_path(
711 check_found_path_abs(code, "core::fmt::Error"); 729 code,
730 "core::fmt::Error",
731 "core::fmt::Error",
732 "core::fmt::Error",
733 "core::fmt::Error",
734 );
712 } 735 }
713 736
714 #[test] 737 #[test]
@@ -731,8 +754,13 @@ mod tests {
731 pub struct Arc; 754 pub struct Arc;
732 } 755 }
733 "#; 756 "#;
734 check_found_path(code, "alloc::sync::Arc"); 757 check_found_path(
735 check_found_path_abs(code, "alloc::sync::Arc"); 758 code,
759 "alloc::sync::Arc",
760 "alloc::sync::Arc",
761 "alloc::sync::Arc",
762 "alloc::sync::Arc",
763 );
736 } 764 }
737 765
738 #[test] 766 #[test]
@@ -749,8 +777,13 @@ mod tests {
749 //- /zzz.rs crate:megaalloc 777 //- /zzz.rs crate:megaalloc
750 pub struct Arc; 778 pub struct Arc;
751 "#; 779 "#;
752 check_found_path(code, "megaalloc::Arc"); 780 check_found_path(
753 check_found_path_abs(code, "megaalloc::Arc"); 781 code,
782 "megaalloc::Arc",
783 "megaalloc::Arc",
784 "megaalloc::Arc",
785 "megaalloc::Arc",
786 );
754 } 787 }
755 788
756 #[test] 789 #[test]
@@ -763,9 +796,7 @@ mod tests {
763 pub use u8; 796 pub use u8;
764 } 797 }
765 "#; 798 "#;
766 check_found_path(code, "u8"); 799 check_found_path(code, "u8", "u8", "u8", "u8");
767 check_found_path(code, "u16"); 800 check_found_path(code, "u16", "u16", "u16", "u16");
768 check_found_path_abs(code, "u8");
769 check_found_path_abs(code, "u16");
770 } 801 }
771} 802}
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index a442fb63a..028cae2e7 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -4,17 +4,16 @@ use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc};
4 4
5use base_db::CrateId; 5use base_db::CrateId;
6use fst::{self, Streamer}; 6use fst::{self, Streamer};
7use hir_expand::name::Name;
7use indexmap::{map::Entry, IndexMap}; 8use indexmap::{map::Entry, IndexMap};
9use itertools::Itertools;
8use rustc_hash::{FxHashMap, FxHasher}; 10use rustc_hash::{FxHashMap, FxHasher};
9use smallvec::SmallVec; 11use smallvec::SmallVec;
10use syntax::SmolStr; 12use syntax::SmolStr;
11 13
12use crate::{ 14use crate::{
13 db::DefDatabase, 15 db::DefDatabase, item_scope::ItemInNs, visibility::Visibility, AssocItemId, ModuleDefId,
14 item_scope::ItemInNs, 16 ModuleId, TraitId,
15 path::{ModPath, PathKind},
16 visibility::Visibility,
17 AssocItemId, ModuleDefId, ModuleId, TraitId,
18}; 17};
19 18
20type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>; 19type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
@@ -23,11 +22,28 @@ type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
23#[derive(Debug, Clone, Eq, PartialEq)] 22#[derive(Debug, Clone, Eq, PartialEq)]
24pub struct ImportInfo { 23pub struct ImportInfo {
25 /// A path that can be used to import the item, relative to the crate's root. 24 /// A path that can be used to import the item, relative to the crate's root.
26 pub path: ModPath, 25 pub path: ImportPath,
27 /// The module containing this item. 26 /// The module containing this item.
28 pub container: ModuleId, 27 pub container: ModuleId,
29} 28}
30 29
30#[derive(Debug, Clone, Eq, PartialEq)]
31pub struct ImportPath {
32 pub segments: Vec<Name>,
33}
34
35impl fmt::Display for ImportPath {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 fmt::Display::fmt(&self.segments.iter().format("::"), f)
38 }
39}
40
41impl ImportPath {
42 fn len(&self) -> usize {
43 self.segments.len()
44 }
45}
46
31/// A map from publicly exported items to the path needed to import/name them from a downstream 47/// A map from publicly exported items to the path needed to import/name them from a downstream
32/// crate. 48/// crate.
33/// 49///
@@ -61,7 +77,7 @@ impl ImportMap {
61 let mut import_map = Self::default(); 77 let mut import_map = Self::default();
62 78
63 // We look only into modules that are public(ly reexported), starting with the crate root. 79 // We look only into modules that are public(ly reexported), starting with the crate root.
64 let empty = ModPath { kind: PathKind::Plain, segments: vec![] }; 80 let empty = ImportPath { segments: vec![] };
65 let root = ModuleId { krate, local_id: def_map.root }; 81 let root = ModuleId { krate, local_id: def_map.root };
66 let mut worklist = vec![(root, empty)]; 82 let mut worklist = vec![(root, empty)];
67 while let Some((module, mod_path)) = worklist.pop() { 83 while let Some((module, mod_path)) = worklist.pop() {
@@ -152,8 +168,8 @@ impl ImportMap {
152 } 168 }
153 169
154 /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. 170 /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root.
155 pub fn path_of(&self, item: ItemInNs) -> Option<&ModPath> { 171 pub fn path_of(&self, item: ItemInNs) -> Option<&ImportPath> {
156 Some(&self.map.get(&item)?.path) 172 self.import_info_for(item).map(|it| &it.path)
157 } 173 }
158 174
159 pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> { 175 pub fn import_info_for(&self, item: ItemInNs) -> Option<&ImportInfo> {
@@ -197,7 +213,7 @@ impl fmt::Debug for ImportMap {
197 } 213 }
198} 214}
199 215
200fn fst_path(path: &ModPath) -> String { 216fn fst_path(path: &ImportPath) -> String {
201 let mut s = path.to_string(); 217 let mut s = path.to_string();
202 s.make_ascii_lowercase(); 218 s.make_ascii_lowercase();
203 s 219 s
@@ -334,14 +350,14 @@ mod tests {
334 350
335 use super::*; 351 use super::*;
336 352
337 fn check_search(ra_fixture: &str, krate_name: &str, query: Query, expect: Expect) { 353 fn check_search(ra_fixture: &str, crate_name: &str, query: Query, expect: Expect) {
338 let db = TestDB::with_files(ra_fixture); 354 let db = TestDB::with_files(ra_fixture);
339 let crate_graph = db.crate_graph(); 355 let crate_graph = db.crate_graph();
340 let krate = crate_graph 356 let krate = crate_graph
341 .iter() 357 .iter()
342 .find(|krate| { 358 .find(|krate| {
343 crate_graph[*krate].display_name.as_ref().map(|n| n.to_string()) 359 crate_graph[*krate].declaration_name.as_ref().map(|n| n.to_string())
344 == Some(krate_name.to_string()) 360 == Some(crate_name.to_string())
345 }) 361 })
346 .unwrap(); 362 .unwrap();
347 363
@@ -359,7 +375,7 @@ mod tests {
359 let path = map.path_of(item).unwrap(); 375 let path = map.path_of(item).unwrap();
360 format!( 376 format!(
361 "{}::{} ({})\n", 377 "{}::{} ({})\n",
362 crate_graph[krate].display_name.as_ref().unwrap(), 378 crate_graph[krate].declaration_name.as_ref().unwrap(),
363 path, 379 path,
364 mark 380 mark
365 ) 381 )
@@ -400,7 +416,7 @@ mod tests {
400 .iter() 416 .iter()
401 .filter_map(|krate| { 417 .filter_map(|krate| {
402 let cdata = &crate_graph[krate]; 418 let cdata = &crate_graph[krate];
403 let name = cdata.display_name.as_ref()?; 419 let name = cdata.declaration_name.as_ref()?;
404 420
405 let map = db.import_map(krate); 421 let map = db.import_map(krate);
406 422
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 5e4d73c1f..464ffef21 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -173,7 +173,7 @@ impl CrateDefMap {
173 pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 173 pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
174 let _p = profile::span("crate_def_map_query").detail(|| { 174 let _p = profile::span("crate_def_map_query").detail(|| {
175 db.crate_graph()[krate] 175 db.crate_graph()[krate]
176 .display_name 176 .declaration_name
177 .as_ref() 177 .as_ref()
178 .map(ToString::to_string) 178 .map(ToString::to_string)
179 .unwrap_or_default() 179 .unwrap_or_default()
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 100e25ffc..c8cd04264 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1229,9 +1229,10 @@ impl ModCollector<'_, '_> {
1229 } else { 1229 } else {
1230 let derive = attrs.by_key("proc_macro_derive"); 1230 let derive = attrs.by_key("proc_macro_derive");
1231 if let Some(arg) = derive.tt_values().next() { 1231 if let Some(arg) = derive.tt_values().next() {
1232 if let [TokenTree::Leaf(Leaf::Ident(trait_name))] = &*arg.token_trees { 1232 if let [TokenTree::Leaf(Leaf::Ident(trait_name)), ..] = &*arg.token_trees {
1233 trait_name.as_name() 1233 trait_name.as_name()
1234 } else { 1234 } else {
1235 log::trace!("malformed `#[proc_macro_derive]`: {}", arg);
1235 return; 1236 return;
1236 } 1237 }
1237 } else { 1238 } else {
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 0851c3b7d..305fca0f9 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -688,13 +688,20 @@ fn resolves_proc_macros() {
688 pub fn derive_macro(_item: TokenStream) -> TokenStream { 688 pub fn derive_macro(_item: TokenStream) -> TokenStream {
689 TokenStream 689 TokenStream
690 } 690 }
691
692 #[proc_macro_derive(AnotherTrait, attributes(helper_attr))]
693 pub fn derive_macro_2(_item: TokenStream) -> TokenStream {
694 TokenStream
695 }
691 ", 696 ",
692 expect![[r#" 697 expect![[r#"
693 crate 698 crate
699 AnotherTrait: m
694 DummyTrait: m 700 DummyTrait: m
695 TokenStream: t v 701 TokenStream: t v
696 attribute_macro: v m 702 attribute_macro: v m
697 derive_macro: v 703 derive_macro: v
704 derive_macro_2: v
698 function_like_macro: v m 705 function_like_macro: v m
699 "#]], 706 "#]],
700 ); 707 );
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 209b18e78..5b8c1e449 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 hygiene::Hygiene, 13 hygiene::Hygiene,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15}; 15};
16use syntax::ast::{self, make}; 16use syntax::ast::{self};
17 17
18use crate::{ 18use crate::{
19 type_ref::{TypeBound, TypeRef}, 19 type_ref::{TypeBound, TypeRef},
@@ -100,26 +100,6 @@ impl ModPath {
100 } 100 }
101 self.segments.first() 101 self.segments.first()
102 } 102 }
103
104 pub fn to_ast_path(&self) -> ast::Path {
105 let mut segments = Vec::new();
106 let mut is_abs = false;
107 match self.kind {
108 PathKind::Plain => {}
109 PathKind::Super(0) => segments.push(make::path_segment_self()),
110 PathKind::Super(n) => segments.extend((0..n).map(|_| make::path_segment_super())),
111 PathKind::Crate => segments.push(make::path_segment_crate()),
112 PathKind::Abs => is_abs = true,
113 PathKind::DollarCrate(_) => (),
114 }
115
116 segments.extend(
117 self.segments
118 .iter()
119 .map(|segment| make::path_segment(make::name_ref(&segment.to_string()))),
120 );
121 make::path_from_segments(segments, is_abs)
122 }
123} 103}
124 104
125#[derive(Debug, Clone, PartialEq, Eq, Hash)] 105#[derive(Debug, Clone, PartialEq, Eq, Hash)]