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.rs247
1 files changed, 138 insertions, 109 deletions
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index baf374144..9106ed45f 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
@@ -226,7 +237,7 @@ fn find_path_inner(
226 } 237 }
227 } 238 }
228 239
229 if let Some(prefix) = prefixed.prefix() { 240 if let Some(prefix) = prefixed.map(PrefixKind::prefix) {
230 best_path.or_else(|| { 241 best_path.or_else(|| {
231 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name])) 242 scope_name.map(|scope_name| ModPath::from_segments(prefix, vec![scope_name]))
232 }) 243 })
@@ -355,7 +366,7 @@ mod tests {
355 /// `code` needs to contain a cursor marker; checks that `find_path` for the 366 /// `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 367 /// item the `path` refers to returns that same path when called from the
357 /// module the cursor is in. 368 /// module the cursor is in.
358 fn check_found_path_(ra_fixture: &str, path: &str, absolute: bool) { 369 fn check_found_path_(ra_fixture: &str, path: &str, prefix_kind: Option<PrefixKind>) {
359 let (db, pos) = TestDB::with_position(ra_fixture); 370 let (db, pos) = TestDB::with_position(ra_fixture);
360 let module = db.module_for_file(pos.file_id); 371 let module = db.module_for_file(pos.file_id);
361 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path)); 372 let parsed_path_file = syntax::SourceFile::parse(&format!("use {};", path));
@@ -375,20 +386,22 @@ mod tests {
375 .take_types() 386 .take_types()
376 .unwrap(); 387 .unwrap();
377 388
378 let found_path = if absolute { find_path_prefixed } else { find_path }( 389 let found_path =
379 &db, 390 find_path_inner(&db, ItemInNs::Types(resolved), module, MAX_PATH_LEN, prefix_kind);
380 ItemInNs::Types(resolved), 391 assert_eq!(found_path, Some(mod_path), "{:?}", prefix_kind);
381 module,
382 );
383 assert_eq!(found_path, Some(mod_path), "absolute {}", absolute);
384 } 392 }
385 393
386 fn check_found_path(ra_fixture: &str, path: &str) { 394 fn check_found_path(
387 check_found_path_(ra_fixture, path, false); 395 ra_fixture: &str,
388 } 396 unprefixed: &str,
389 397 prefixed: &str,
390 fn check_found_path_abs(ra_fixture: &str, path: &str) { 398 absolute: &str,
391 check_found_path_(ra_fixture, path, true); 399 self_prefixed: &str,
400 ) {
401 check_found_path_(ra_fixture, unprefixed, None);
402 check_found_path_(ra_fixture, prefixed, Some(PrefixKind::Plain));
403 check_found_path_(ra_fixture, absolute, Some(PrefixKind::ByCrate));
404 check_found_path_(ra_fixture, self_prefixed, Some(PrefixKind::BySelf));
392 } 405 }
393 406
394 #[test] 407 #[test]
@@ -398,8 +411,7 @@ mod tests {
398 struct S; 411 struct S;
399 <|> 412 <|>
400 "#; 413 "#;
401 check_found_path(code, "S"); 414 check_found_path(code, "S", "S", "crate::S", "self::S");
402 check_found_path_abs(code, "S");
403 } 415 }
404 416
405 #[test] 417 #[test]
@@ -409,8 +421,7 @@ mod tests {
409 enum E { A } 421 enum E { A }
410 <|> 422 <|>
411 "#; 423 "#;
412 check_found_path(code, "E::A"); 424 check_found_path(code, "E::A", "E::A", "E::A", "E::A");
413 check_found_path_abs(code, "E::A");
414 } 425 }
415 426
416 #[test] 427 #[test]
@@ -422,8 +433,7 @@ mod tests {
422 } 433 }
423 <|> 434 <|>
424 "#; 435 "#;
425 check_found_path(code, "foo::S"); 436 check_found_path(code, "foo::S", "foo::S", "crate::foo::S", "self::foo::S");
426 check_found_path_abs(code, "foo::S");
427 } 437 }
428 438
429 #[test] 439 #[test]
@@ -437,8 +447,7 @@ mod tests {
437 //- /foo/bar.rs 447 //- /foo/bar.rs
438 <|> 448 <|>
439 "#; 449 "#;
440 check_found_path(code, "super::S"); 450 check_found_path(code, "super::S", "super::S", "crate::foo::S", "super::S");
441 check_found_path_abs(code, "super::S");
442 } 451 }
443 452
444 #[test] 453 #[test]
@@ -449,8 +458,7 @@ mod tests {
449 //- /foo.rs 458 //- /foo.rs
450 <|> 459 <|>
451 "#; 460 "#;
452 check_found_path(code, "self"); 461 check_found_path(code, "self", "self", "crate::foo", "self");
453 check_found_path_abs(code, "self");
454 } 462 }
455 463
456 #[test] 464 #[test]
@@ -461,8 +469,7 @@ mod tests {
461 //- /foo.rs 469 //- /foo.rs
462 <|> 470 <|>
463 "#; 471 "#;
464 check_found_path(code, "crate"); 472 check_found_path(code, "crate", "crate", "crate", "crate");
465 check_found_path_abs(code, "crate");
466 } 473 }
467 474
468 #[test] 475 #[test]
@@ -474,8 +481,7 @@ mod tests {
474 //- /foo.rs 481 //- /foo.rs
475 <|> 482 <|>
476 "#; 483 "#;
477 check_found_path(code, "crate::S"); 484 check_found_path(code, "crate::S", "crate::S", "crate::S", "crate::S");
478 check_found_path_abs(code, "crate::S");
479 } 485 }
480 486
481 #[test] 487 #[test]
@@ -486,8 +492,7 @@ mod tests {
486 //- /std.rs crate:std 492 //- /std.rs crate:std
487 pub struct S; 493 pub struct S;
488 "#; 494 "#;
489 check_found_path(code, "std::S"); 495 check_found_path(code, "std::S", "std::S", "std::S", "std::S");
490 check_found_path_abs(code, "std::S");
491 } 496 }
492 497
493 #[test] 498 #[test]
@@ -499,8 +504,13 @@ mod tests {
499 //- /std.rs crate:std 504 //- /std.rs crate:std
500 pub struct S; 505 pub struct S;
501 "#; 506 "#;
502 check_found_path(code, "std_renamed::S"); 507 check_found_path(
503 check_found_path_abs(code, "std_renamed::S"); 508 code,
509 "std_renamed::S",
510 "std_renamed::S",
511 "std_renamed::S",
512 "std_renamed::S",
513 );
504 } 514 }
505 515
506 #[test] 516 #[test]
@@ -520,8 +530,13 @@ mod tests {
520 } 530 }
521 } 531 }
522 "#; 532 "#;
523 check_found_path(code, "ast::ModuleItem"); 533 check_found_path(
524 check_found_path_abs(code, "syntax::ast::ModuleItem"); 534 code,
535 "ast::ModuleItem",
536 "syntax::ast::ModuleItem",
537 "syntax::ast::ModuleItem",
538 "syntax::ast::ModuleItem",
539 );
525 540
526 let code = r#" 541 let code = r#"
527 //- /main.rs crate:main deps:syntax 542 //- /main.rs crate:main deps:syntax
@@ -535,8 +550,13 @@ mod tests {
535 } 550 }
536 } 551 }
537 "#; 552 "#;
538 check_found_path(code, "syntax::ast::ModuleItem"); 553 check_found_path(
539 check_found_path_abs(code, "syntax::ast::ModuleItem"); 554 code,
555 "syntax::ast::ModuleItem",
556 "syntax::ast::ModuleItem",
557 "syntax::ast::ModuleItem",
558 "syntax::ast::ModuleItem",
559 );
540 } 560 }
541 561
542 #[test] 562 #[test]
@@ -549,8 +569,7 @@ mod tests {
549 } 569 }
550 <|> 570 <|>
551 "#; 571 "#;
552 check_found_path(code, "bar::S"); 572 check_found_path(code, "bar::S", "bar::S", "crate::bar::S", "self::bar::S");
553 check_found_path_abs(code, "bar::S");
554 } 573 }
555 574
556 #[test] 575 #[test]
@@ -563,8 +582,7 @@ mod tests {
563 } 582 }
564 <|> 583 <|>
565 "#; 584 "#;
566 check_found_path(code, "bar::U"); 585 check_found_path(code, "bar::U", "bar::U", "crate::bar::U", "self::bar::U");
567 check_found_path_abs(code, "bar::U");
568 } 586 }
569 587
570 #[test] 588 #[test]
@@ -577,8 +595,7 @@ mod tests {
577 //- /core.rs crate:core 595 //- /core.rs crate:core
578 pub struct S; 596 pub struct S;
579 "#; 597 "#;
580 check_found_path(code, "std::S"); 598 check_found_path(code, "std::S", "std::S", "std::S", "std::S");
581 check_found_path_abs(code, "std::S");
582 } 599 }
583 600
584 #[test] 601 #[test]
@@ -591,8 +608,7 @@ mod tests {
591 #[prelude_import] 608 #[prelude_import]
592 pub use prelude::*; 609 pub use prelude::*;
593 "#; 610 "#;
594 check_found_path(code, "S"); 611 check_found_path(code, "S", "S", "S", "S");
595 check_found_path_abs(code, "S");
596 } 612 }
597 613
598 #[test] 614 #[test]
@@ -608,10 +624,8 @@ mod tests {
608 #[prelude_import] 624 #[prelude_import]
609 pub use prelude::*; 625 pub use prelude::*;
610 "#; 626 "#;
611 check_found_path(code, "None"); 627 check_found_path(code, "None", "None", "None", "None");
612 check_found_path(code, "Some"); 628 check_found_path(code, "Some", "Some", "Some", "Some");
613 check_found_path_abs(code, "None");
614 check_found_path_abs(code, "Some");
615 } 629 }
616 630
617 #[test] 631 #[test]
@@ -627,8 +641,7 @@ mod tests {
627 //- /baz.rs 641 //- /baz.rs
628 pub use crate::foo::bar::S; 642 pub use crate::foo::bar::S;
629 "#; 643 "#;
630 check_found_path(code, "baz::S"); 644 check_found_path(code, "baz::S", "baz::S", "crate::baz::S", "self::baz::S");
631 check_found_path_abs(code, "baz::S");
632 } 645 }
633 646
634 #[test] 647 #[test]
@@ -642,8 +655,7 @@ mod tests {
642 <|> 655 <|>
643 "#; 656 "#;
644 // crate::S would be shorter, but using private imports seems wrong 657 // crate::S would be shorter, but using private imports seems wrong
645 check_found_path(code, "crate::bar::S"); 658 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 } 659 }
648 660
649 #[test] 661 #[test]
@@ -661,8 +673,7 @@ mod tests {
661 //- /baz.rs 673 //- /baz.rs
662 pub use super::foo; 674 pub use super::foo;
663 "#; 675 "#;
664 check_found_path(code, "crate::foo::S"); 676 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 } 677 }
667 678
668 #[test] 679 #[test]
@@ -682,8 +693,13 @@ mod tests {
682 pub struct Arc; 693 pub struct Arc;
683 } 694 }
684 "#; 695 "#;
685 check_found_path(code, "std::sync::Arc"); 696 check_found_path(
686 check_found_path_abs(code, "std::sync::Arc"); 697 code,
698 "std::sync::Arc",
699 "std::sync::Arc",
700 "std::sync::Arc",
701 "std::sync::Arc",
702 );
687 } 703 }
688 704
689 #[test] 705 #[test]
@@ -707,8 +723,13 @@ mod tests {
707 pub struct Error; 723 pub struct Error;
708 } 724 }
709 "#; 725 "#;
710 check_found_path(code, "core::fmt::Error"); 726 check_found_path(
711 check_found_path_abs(code, "core::fmt::Error"); 727 code,
728 "core::fmt::Error",
729 "core::fmt::Error",
730 "core::fmt::Error",
731 "core::fmt::Error",
732 );
712 } 733 }
713 734
714 #[test] 735 #[test]
@@ -731,8 +752,13 @@ mod tests {
731 pub struct Arc; 752 pub struct Arc;
732 } 753 }
733 "#; 754 "#;
734 check_found_path(code, "alloc::sync::Arc"); 755 check_found_path(
735 check_found_path_abs(code, "alloc::sync::Arc"); 756 code,
757 "alloc::sync::Arc",
758 "alloc::sync::Arc",
759 "alloc::sync::Arc",
760 "alloc::sync::Arc",
761 );
736 } 762 }
737 763
738 #[test] 764 #[test]
@@ -749,8 +775,13 @@ mod tests {
749 //- /zzz.rs crate:megaalloc 775 //- /zzz.rs crate:megaalloc
750 pub struct Arc; 776 pub struct Arc;
751 "#; 777 "#;
752 check_found_path(code, "megaalloc::Arc"); 778 check_found_path(
753 check_found_path_abs(code, "megaalloc::Arc"); 779 code,
780 "megaalloc::Arc",
781 "megaalloc::Arc",
782 "megaalloc::Arc",
783 "megaalloc::Arc",
784 );
754 } 785 }
755 786
756 #[test] 787 #[test]
@@ -763,9 +794,7 @@ mod tests {
763 pub use u8; 794 pub use u8;
764 } 795 }
765 "#; 796 "#;
766 check_found_path(code, "u8"); 797 check_found_path(code, "u8", "u8", "u8", "u8");
767 check_found_path(code, "u16"); 798 check_found_path(code, "u16", "u16", "u16", "u16");
768 check_found_path_abs(code, "u8");
769 check_found_path_abs(code, "u16");
770 } 799 }
771} 800}