1use std::{cell::Cell, cmp::Ordering, iter};
4
5use base_db::{Crate, CrateOrigin, LangCrateOrigin};
6use hir_expand::{
7 Lookup,
8 mod_path::{ModPath, PathKind},
9 name::{AsName, Name},
10};
11use intern::sym;
12use rustc_hash::FxHashSet;
13
14use crate::{
15 ImportPathConfig, ModuleDefId, ModuleId,
16 db::DefDatabase,
17 item_scope::ItemInNs,
18 nameres::DefMap,
19 visibility::{Visibility, VisibilityExplicitness},
20};
21
22pub fn find_path(
25 db: &dyn DefDatabase,
26 item: ItemInNs,
27 from: ModuleId,
28 mut prefix_kind: PrefixKind,
29 ignore_local_imports: bool,
30 mut cfg: ImportPathConfig,
31) -> Option<ModPath> {
32 let _p = tracing::info_span!("find_path").entered();
33
34 if let ItemInNs::Types(ModuleDefId::BuiltinType(builtin)) = item {
36 return Some(ModPath::from_segments(PathKind::Plain, iter::once(builtin.as_name())));
37 }
38
39 let item_module = item.module(db)?;
42 if item_module.is_within_block() {
43 prefix_kind = PrefixKind::Plain;
44 }
45 cfg.prefer_no_std = cfg.prefer_no_std || db.crate_supports_no_std(from.krate());
46
47 find_path_inner(
48 &FindPathCtx {
49 db,
50 prefix: prefix_kind,
51 cfg,
52 ignore_local_imports,
53 is_std_item: item_module.krate().data(db).origin.is_lang(),
54 from,
55 from_def_map: from.def_map(db),
56 fuel: Cell::new(FIND_PATH_FUEL),
57 },
58 item,
59 MAX_PATH_LEN,
60 )
61}
62
63#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
64enum Stability {
65 Unstable,
66 Stable,
67}
68use Stability::*;
69
70const MAX_PATH_LEN: usize = 15;
71const FIND_PATH_FUEL: usize = 10000;
72
73#[derive(Copy, Clone, Debug, PartialEq, Eq)]
74pub enum PrefixKind {
75 BySelf,
79 Plain,
81 ByCrate,
83}
84
85impl PrefixKind {
86 #[inline]
87 fn path_kind(self) -> PathKind {
88 match self {
89 PrefixKind::BySelf => PathKind::SELF,
90 PrefixKind::Plain => PathKind::Plain,
91 PrefixKind::ByCrate => PathKind::Crate,
92 }
93 }
94}
95
96struct FindPathCtx<'db> {
97 db: &'db dyn DefDatabase,
98 prefix: PrefixKind,
99 cfg: ImportPathConfig,
100 ignore_local_imports: bool,
101 is_std_item: bool,
102 from: ModuleId,
103 from_def_map: &'db DefMap,
104 fuel: Cell<usize>,
105}
106
107fn find_path_inner(ctx: &FindPathCtx<'_>, item: ItemInNs, max_len: usize) -> Option<ModPath> {
109 if !ctx.is_std_item
111 && let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item
112 {
113 return find_path_for_module(ctx, &mut FxHashSet::default(), module_id, true, max_len)
114 .map(|choice| choice.path);
115 }
116
117 let may_be_in_scope = match ctx.prefix {
118 PrefixKind::Plain | PrefixKind::BySelf => true,
119 PrefixKind::ByCrate => ctx.from.is_crate_root(),
120 };
121 if may_be_in_scope {
122 let scope_name =
124 find_in_scope(ctx.db, ctx.from_def_map, ctx.from, item, ctx.ignore_local_imports);
125 if let Some(scope_name) = scope_name {
126 return Some(ModPath::from_segments(ctx.prefix.path_kind(), iter::once(scope_name)));
127 }
128 }
129
130 if let Some(value) = find_in_prelude(ctx.db, ctx.from_def_map, item, ctx.from) {
132 return Some(value.path);
133 }
134
135 if let Some(ModuleDefId::EnumVariantId(variant)) = item.as_module_def_id() {
136 let loc = variant.lookup(ctx.db);
138 if let Some(mut path) = find_path_inner(ctx, ItemInNs::Types(loc.parent.into()), max_len) {
139 path.push_segment(
140 loc.parent.enum_variants(ctx.db).variants[loc.index as usize].1.clone(),
141 );
142 return Some(path);
143 }
144 }
148
149 let mut best_choice = None;
150 calculate_best_path(ctx, &mut FxHashSet::default(), item, max_len, &mut best_choice);
151 best_choice.map(|choice| choice.path)
152}
153
154#[tracing::instrument(skip_all)]
155fn find_path_for_module(
156 ctx: &FindPathCtx<'_>,
157 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
158 module_id: ModuleId,
159 maybe_extern: bool,
160 max_len: usize,
161) -> Option<Choice> {
162 if max_len == 0 {
163 return None;
165 }
166 if let Some(crate_root) = module_id.as_crate_root() {
167 if !maybe_extern || crate_root == ctx.from.derive_crate_root() {
168 return Some(Choice {
170 path: ModPath::from_segments(PathKind::Crate, None),
171 path_text_len: 5,
172 stability: Stable,
173 prefer_due_to_prelude: false,
174 });
175 }
176 let root_local_def_map = ctx.from.derive_crate_root().local_def_map(ctx.db).1;
179 for (name, (def_id, _extern_crate)) in root_local_def_map.extern_prelude().rev() {
181 if crate_root != def_id {
182 continue;
183 }
184 let name_already_occupied_in_type_ns = ctx
185 .from_def_map
186 .with_ancestor_maps(ctx.db, ctx.from.local_id, &mut |def_map, local_id| {
187 def_map[local_id]
188 .scope
189 .type_(name)
190 .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into()))
191 })
192 .is_some();
193 let kind = if name_already_occupied_in_type_ns {
194 cov_mark::hit!(ambiguous_crate_start);
195 PathKind::Abs
196 } else if ctx.cfg.prefer_absolute {
197 PathKind::Abs
198 } else {
199 PathKind::Plain
200 };
201 return Some(Choice::new(ctx.cfg.prefer_prelude, kind, name.clone(), Stable));
202 }
203 }
204
205 let may_be_in_scope = match ctx.prefix {
206 PrefixKind::Plain | PrefixKind::BySelf => true,
207 PrefixKind::ByCrate => ctx.from.is_crate_root(),
208 };
209 if may_be_in_scope {
210 let scope_name = find_in_scope(
211 ctx.db,
212 ctx.from_def_map,
213 ctx.from,
214 ItemInNs::Types(module_id.into()),
215 ctx.ignore_local_imports,
216 );
217 if let Some(scope_name) = scope_name {
218 return Some(Choice::new(
220 ctx.cfg.prefer_prelude,
221 ctx.prefix.path_kind(),
222 scope_name,
223 Stable,
224 ));
225 }
226 }
227
228 if let Some(kind) = is_kw_kind_relative_to_from(ctx.from_def_map, module_id, ctx.from)
230 && (ctx.prefix != PrefixKind::ByCrate || kind == PathKind::Crate)
231 {
232 return Some(Choice {
233 path: ModPath::from_segments(kind, None),
234 path_text_len: path_kind_len(kind),
235 stability: Stable,
236 prefer_due_to_prelude: false,
237 });
238 }
239
240 let item = ItemInNs::Types(module_id.into());
242 if let Some(choice) = find_in_prelude(ctx.db, ctx.from_def_map, item, ctx.from) {
243 return Some(choice);
244 }
245 let mut best_choice = None;
246 if maybe_extern {
247 calculate_best_path(ctx, visited_modules, item, max_len, &mut best_choice);
248 } else {
249 calculate_best_path_local(ctx, visited_modules, item, max_len, &mut best_choice);
250 }
251 best_choice
252}
253
254fn find_in_scope(
255 db: &dyn DefDatabase,
256 def_map: &DefMap,
257 from: ModuleId,
258 item: ItemInNs,
259 ignore_local_imports: bool,
260) -> Option<Name> {
261 def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
263 def_map[local_id].scope.names_of(item, |name, _, declared| {
264 (declared || !ignore_local_imports).then(|| name.clone())
265 })
266 })
267}
268
269fn find_in_prelude(
272 db: &dyn DefDatabase,
273 local_def_map: &DefMap,
274 item: ItemInNs,
275 from: ModuleId,
276) -> Option<Choice> {
277 let (prelude_module, _) = local_def_map.prelude()?;
278 let prelude_def_map = prelude_module.def_map(db);
279 let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
280 let (name, vis, _declared) = prelude_scope.name_of(item)?;
281 if !vis.is_visible_from(db, from) {
282 return None;
283 }
284
285 let found_and_same_def =
287 local_def_map.with_ancestor_maps(db, from.local_id, &mut |def_map, local_id| {
288 let per_ns = def_map[local_id].scope.get(name);
289 let same_def = match item {
290 ItemInNs::Types(it) => per_ns.take_types()? == it,
291 ItemInNs::Values(it) => per_ns.take_values()? == it,
292 ItemInNs::Macros(it) => per_ns.take_macros()? == it,
293 };
294 Some(same_def)
295 });
296
297 if found_and_same_def.unwrap_or(true) {
298 Some(Choice::new(false, PathKind::Plain, name.clone(), Stable))
299 } else {
300 None
301 }
302}
303
304fn is_kw_kind_relative_to_from(
305 def_map: &DefMap,
306 item: ModuleId,
307 from: ModuleId,
308) -> Option<PathKind> {
309 if item.krate != from.krate || item.is_within_block() || from.is_within_block() {
310 return None;
311 }
312 let item = item.local_id;
313 let from = from.local_id;
314 if item == from {
315 Some(PathKind::SELF)
317 } else if let Some(parent_id) = def_map[from].parent {
318 if item == parent_id {
319 Some(if parent_id == DefMap::ROOT { PathKind::Crate } else { PathKind::Super(1) })
321 } else {
322 None
323 }
324 } else {
325 None
326 }
327}
328
329#[tracing::instrument(skip_all)]
330fn calculate_best_path(
331 ctx: &FindPathCtx<'_>,
332 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
333 item: ItemInNs,
334 max_len: usize,
335 best_choice: &mut Option<Choice>,
336) {
337 let fuel = ctx.fuel.get();
338 if fuel == 0 {
339 tracing::warn!(
341 "ran out of fuel while searching for a path for item {item:?} of krate {:?} from krate {:?}",
342 item.krate(ctx.db),
343 ctx.from.krate()
344 );
345 return;
346 }
347 ctx.fuel.set(fuel - 1);
348
349 if item.krate(ctx.db) == Some(ctx.from.krate) {
350 calculate_best_path_local(ctx, visited_modules, item, max_len, best_choice)
353 } else if ctx.is_std_item {
354 find_in_sysroot(ctx, visited_modules, item, max_len, best_choice)
359 } else {
360 ctx.from.krate.data(ctx.db).dependencies.iter().for_each(|dep| {
365 find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id)
366 });
367 }
368}
369
370fn find_in_sysroot(
371 ctx: &FindPathCtx<'_>,
372 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
373 item: ItemInNs,
374 max_len: usize,
375 best_choice: &mut Option<Choice>,
376) {
377 let dependencies = &ctx.from.krate.data(ctx.db).dependencies;
378 let mut search = |lang, best_choice: &mut _| {
379 if let Some(dep) = dependencies.iter().filter(|it| it.is_sysroot()).find(|dep| {
380 match dep.crate_id.data(ctx.db).origin {
381 CrateOrigin::Lang(l) => l == lang,
382 _ => false,
383 }
384 }) {
385 find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id);
386 }
387 };
388 if ctx.cfg.prefer_no_std {
389 search(LangCrateOrigin::Core, best_choice);
390 if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
391 return;
392 }
393 search(LangCrateOrigin::Std, best_choice);
394 if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
395 return;
396 }
397 } else {
398 search(LangCrateOrigin::Std, best_choice);
399 if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
400 return;
401 }
402 search(LangCrateOrigin::Core, best_choice);
403 if matches!(best_choice, Some(Choice { stability: Stable, .. })) {
404 return;
405 }
406 }
407 dependencies
408 .iter()
409 .filter(|it| it.is_sysroot())
410 .chain(dependencies.iter().filter(|it| !it.is_sysroot()))
411 .for_each(|dep| {
412 find_in_dep(ctx, visited_modules, item, max_len, best_choice, dep.crate_id);
413 });
414}
415
416fn find_in_dep(
417 ctx: &FindPathCtx<'_>,
418 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
419 item: ItemInNs,
420 max_len: usize,
421 best_choice: &mut Option<Choice>,
422 dep: Crate,
423) {
424 let import_map = ctx.db.import_map(dep);
425 let Some(import_info_for) = import_map.import_info_for(item) else {
426 return;
427 };
428 for info in import_info_for {
429 if info.is_doc_hidden {
430 continue;
432 }
433
434 let choice = find_path_for_module(
437 ctx,
438 visited_modules,
439 info.container,
440 true,
441 best_choice.as_ref().map_or(max_len, |it| it.path.len()) - 1,
442 );
443 let Some(mut choice) = choice else {
444 continue;
445 };
446 cov_mark::hit!(partially_imported);
447 if info.is_unstable {
448 if !ctx.cfg.allow_unstable {
449 continue;
451 }
452 choice.stability = Unstable;
453 }
454
455 Choice::try_select(best_choice, choice, ctx.cfg.prefer_prelude, info.name.clone());
456 }
457}
458
459fn calculate_best_path_local(
460 ctx: &FindPathCtx<'_>,
461 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
462 item: ItemInNs,
463 max_len: usize,
464 best_choice: &mut Option<Choice>,
465) {
466 find_local_import_locations(
468 ctx.db,
469 item,
470 ctx.from,
471 ctx.from_def_map,
472 visited_modules,
473 |visited_modules, name, module_id| {
474 if let Some(choice) = find_path_for_module(
477 ctx,
478 visited_modules,
479 module_id,
480 false,
481 best_choice.as_ref().map_or(max_len, |it| it.path.len()) - 1,
482 ) {
483 Choice::try_select(best_choice, choice, ctx.cfg.prefer_prelude, name.clone());
484 }
485 },
486 );
487}
488
489#[derive(Debug)]
490struct Choice {
491 path: ModPath,
492 path_text_len: usize,
494 stability: Stability,
496 prefer_due_to_prelude: bool,
498}
499
500impl Choice {
501 fn new(prefer_prelude: bool, kind: PathKind, name: Name, stability: Stability) -> Self {
502 Self {
503 path_text_len: path_kind_len(kind) + name.as_str().len(),
504 stability,
505 prefer_due_to_prelude: prefer_prelude && name == sym::prelude,
506 path: ModPath::from_segments(kind, iter::once(name)),
507 }
508 }
509
510 fn push(mut self, prefer_prelude: bool, name: Name) -> Self {
511 self.path_text_len += name.as_str().len();
512 self.prefer_due_to_prelude |= prefer_prelude && name == sym::prelude;
513 self.path.push_segment(name);
514 self
515 }
516
517 fn try_select(
518 current: &mut Option<Choice>,
519 mut other: Choice,
520 prefer_prelude: bool,
521 name: Name,
522 ) {
523 let Some(current) = current else {
524 *current = Some(other.push(prefer_prelude, name));
525 return;
526 };
527 match other
528 .stability
529 .cmp(¤t.stability)
530 .then_with(|| other.prefer_due_to_prelude.cmp(¤t.prefer_due_to_prelude))
531 .then_with(|| (current.path.len()).cmp(&(other.path.len() + 1)))
532 {
533 Ordering::Less => return,
534 Ordering::Equal => {
535 other.path_text_len += name.as_str().len();
536 if let Ordering::Less | Ordering::Equal =
537 current.path_text_len.cmp(&other.path_text_len)
538 {
539 return;
540 }
541 }
542 Ordering::Greater => {
543 other.path_text_len += name.as_str().len();
544 }
545 }
546 other.path.push_segment(name);
547 *current = other;
548 }
549}
550
551fn path_kind_len(kind: PathKind) -> usize {
552 match kind {
553 PathKind::Plain => 0,
554 PathKind::Super(0) => 4,
555 PathKind::Super(s) => s as usize * 5,
556 PathKind::Crate => 5,
557 PathKind::Abs => 2,
558 PathKind::DollarCrate(_) => 0,
559 }
560}
561
562fn find_local_import_locations(
564 db: &dyn DefDatabase,
565 item: ItemInNs,
566 from: ModuleId,
567 def_map: &DefMap,
568 visited_modules: &mut FxHashSet<(ItemInNs, ModuleId)>,
569 mut cb: impl FnMut(&mut FxHashSet<(ItemInNs, ModuleId)>, &Name, ModuleId),
570) {
571 let _p = tracing::info_span!("find_local_import_locations").entered();
572
573 let mut worklist = def_map[from.local_id]
580 .children
581 .values()
582 .map(|&child| def_map.module_id(child))
583 .chain(iter::successors(from.containing_module(db), |m| m.containing_module(db)))
584 .zip(iter::repeat(false))
585 .collect::<Vec<_>>();
586
587 let def_map = def_map.crate_root().def_map(db);
588 let mut block_def_map;
589 let mut cursor = 0;
590
591 while let Some(&mut (module, ref mut processed)) = worklist.get_mut(cursor) {
592 cursor += 1;
593 if !visited_modules.insert((item, module)) {
594 continue;
596 }
597 *processed = true;
598 let data = if module.block.is_some() {
599 block_def_map = module.def_map(db);
601 &block_def_map[module.local_id]
602 } else {
603 &def_map[module.local_id]
605 };
606
607 if let Some((name, vis, declared)) = data.scope.name_of(item)
608 && vis.is_visible_from(db, from)
609 {
610 let is_pub_or_explicit = match vis {
611 Visibility::Module(_, VisibilityExplicitness::Explicit) => {
612 cov_mark::hit!(explicit_private_imports);
613 true
614 }
615 Visibility::Module(_, VisibilityExplicitness::Implicit) => {
616 cov_mark::hit!(discount_private_imports);
617 false
618 }
619 Visibility::PubCrate(_) => true,
620 Visibility::Public => true,
621 };
622
623 if declared || is_pub_or_explicit {
629 cb(visited_modules, name, module);
630 }
631 }
632
633 for (module, vis) in data.scope.modules_in_scope() {
635 if module.krate != from.krate {
636 continue;
639 }
640 if visited_modules.contains(&(item, module)) {
641 continue;
642 }
643
644 if vis.is_visible_from(db, from) {
645 worklist.push((module, false));
646 }
647 }
648 }
649 worklist.into_iter().filter(|&(_, processed)| processed).for_each(|(module, _)| {
650 visited_modules.remove(&(item, module));
651 });
652}
653
654#[cfg(test)]
655mod tests {
656 use expect_test::{Expect, expect};
657 use hir_expand::db::ExpandDatabase;
658 use itertools::Itertools;
659 use span::Edition;
660 use stdx::format_to;
661 use syntax::ast::AstNode;
662 use test_fixture::WithFixture;
663
664 use crate::test_db::TestDB;
665
666 use super::*;
667
668 #[track_caller]
672 fn check_found_path_(
673 #[rust_analyzer::rust_fixture] ra_fixture: &str,
674 path: &str,
675 prefer_prelude: bool,
676 prefer_absolute: bool,
677 prefer_no_std: bool,
678 allow_unstable: bool,
679 expect: Expect,
680 ) {
681 let (db, pos) = TestDB::with_position(ra_fixture);
682 let module = db.module_at_position(pos);
683 let parsed_path_file =
684 syntax::SourceFile::parse(&format!("use {path};"), span::Edition::CURRENT);
685 let ast_path =
686 parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
687 let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
688 db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
689 })
690 .unwrap();
691
692 let (def_map, local_def_map) = module.local_def_map(&db);
693 let resolved = def_map
694 .resolve_path(
695 local_def_map,
696 &db,
697 module.local_id,
698 &mod_path,
699 crate::item_scope::BuiltinShadowMode::Module,
700 None,
701 )
702 .0;
703 let resolved = resolved
704 .take_types()
705 .map(ItemInNs::Types)
706 .or_else(|| resolved.take_values().map(ItemInNs::Values))
707 .expect("path does not resolve to a type or value");
708
709 let mut res = String::new();
710 for (prefix, ignore_local_imports) in
711 [PrefixKind::Plain, PrefixKind::ByCrate, PrefixKind::BySelf]
712 .into_iter()
713 .cartesian_product([false, true])
714 {
715 let found_path = find_path(
716 &db,
717 resolved,
718 module,
719 prefix,
720 ignore_local_imports,
721 ImportPathConfig { prefer_no_std, prefer_prelude, prefer_absolute, allow_unstable },
722 );
723 format_to!(
724 res,
725 "{:7}(imports {}): {}\n",
726 format!("{:?}", prefix),
727 if ignore_local_imports { '✖' } else { '✔' },
728 found_path.map_or_else(
729 || "<unresolvable>".to_owned(),
730 |it| it.display(&db, Edition::CURRENT).to_string()
731 ),
732 );
733 }
734 expect.assert_eq(&res);
735 }
736
737 fn check_found_path(
738 #[rust_analyzer::rust_fixture] ra_fixture: &str,
739 path: &str,
740 expect: Expect,
741 ) {
742 check_found_path_(ra_fixture, path, false, false, false, false, expect);
743 }
744
745 fn check_found_path_prelude(
746 #[rust_analyzer::rust_fixture] ra_fixture: &str,
747 path: &str,
748 expect: Expect,
749 ) {
750 check_found_path_(ra_fixture, path, true, false, false, false, expect);
751 }
752
753 fn check_found_path_absolute(
754 #[rust_analyzer::rust_fixture] ra_fixture: &str,
755 path: &str,
756 expect: Expect,
757 ) {
758 check_found_path_(ra_fixture, path, false, true, false, false, expect);
759 }
760
761 fn check_found_path_prefer_no_std(
762 #[rust_analyzer::rust_fixture] ra_fixture: &str,
763 path: &str,
764 expect: Expect,
765 ) {
766 check_found_path_(ra_fixture, path, false, false, true, false, expect);
767 }
768
769 fn check_found_path_prefer_no_std_allow_unstable(
770 #[rust_analyzer::rust_fixture] ra_fixture: &str,
771 path: &str,
772 expect: Expect,
773 ) {
774 check_found_path_(ra_fixture, path, false, false, true, true, expect);
775 }
776
777 #[test]
778 fn same_module() {
779 check_found_path(
780 r#"
781struct S;
782$0
783 "#,
784 "S",
785 expect![[r#"
786 Plain (imports ✔): S
787 Plain (imports ✖): S
788 ByCrate(imports ✔): crate::S
789 ByCrate(imports ✖): crate::S
790 BySelf (imports ✔): self::S
791 BySelf (imports ✖): self::S
792 "#]],
793 );
794 }
795
796 #[test]
797 fn enum_variant() {
798 check_found_path(
799 r#"
800enum E { A }
801$0
802 "#,
803 "E::A",
804 expect![[r#"
805 Plain (imports ✔): E::A
806 Plain (imports ✖): E::A
807 ByCrate(imports ✔): crate::E::A
808 ByCrate(imports ✖): crate::E::A
809 BySelf (imports ✔): self::E::A
810 BySelf (imports ✖): self::E::A
811 "#]],
812 );
813 }
814
815 #[test]
816 fn sub_module() {
817 check_found_path(
818 r#"
819mod foo {
820 pub struct S;
821}
822$0
823 "#,
824 "foo::S",
825 expect![[r#"
826 Plain (imports ✔): foo::S
827 Plain (imports ✖): foo::S
828 ByCrate(imports ✔): crate::foo::S
829 ByCrate(imports ✖): crate::foo::S
830 BySelf (imports ✔): self::foo::S
831 BySelf (imports ✖): self::foo::S
832 "#]],
833 );
834 }
835
836 #[test]
837 fn super_module() {
838 check_found_path(
839 r#"
840//- /main.rs
841mod foo;
842//- /foo.rs
843mod bar;
844struct S;
845//- /foo/bar.rs
846$0
847 "#,
848 "super::S",
849 expect![[r#"
850 Plain (imports ✔): super::S
851 Plain (imports ✖): super::S
852 ByCrate(imports ✔): crate::foo::S
853 ByCrate(imports ✖): crate::foo::S
854 BySelf (imports ✔): super::S
855 BySelf (imports ✖): super::S
856 "#]],
857 );
858 }
859
860 #[test]
861 fn self_module() {
862 check_found_path(
863 r#"
864//- /main.rs
865mod foo;
866//- /foo.rs
867$0
868 "#,
869 "self",
870 expect![[r#"
871 Plain (imports ✔): self
872 Plain (imports ✖): self
873 ByCrate(imports ✔): crate::foo
874 ByCrate(imports ✖): crate::foo
875 BySelf (imports ✔): self
876 BySelf (imports ✖): self
877 "#]],
878 );
879 }
880
881 #[test]
882 fn crate_root() {
883 check_found_path(
884 r#"
885//- /main.rs
886mod foo;
887//- /foo.rs
888$0
889 "#,
890 "crate",
891 expect![[r#"
892 Plain (imports ✔): crate
893 Plain (imports ✖): crate
894 ByCrate(imports ✔): crate
895 ByCrate(imports ✖): crate
896 BySelf (imports ✔): crate
897 BySelf (imports ✖): crate
898 "#]],
899 );
900 }
901
902 #[test]
903 fn same_crate() {
904 check_found_path(
905 r#"
906//- /main.rs
907mod foo;
908struct S;
909//- /foo.rs
910$0
911 "#,
912 "crate::S",
913 expect![[r#"
914 Plain (imports ✔): crate::S
915 Plain (imports ✖): crate::S
916 ByCrate(imports ✔): crate::S
917 ByCrate(imports ✖): crate::S
918 BySelf (imports ✔): crate::S
919 BySelf (imports ✖): crate::S
920 "#]],
921 );
922 }
923
924 #[test]
925 fn different_crate() {
926 check_found_path(
927 r#"
928//- /main.rs crate:main deps:std
929$0
930//- /std.rs crate:std
931pub struct S;
932 "#,
933 "std::S",
934 expect![[r#"
935 Plain (imports ✔): std::S
936 Plain (imports ✖): std::S
937 ByCrate(imports ✔): std::S
938 ByCrate(imports ✖): std::S
939 BySelf (imports ✔): std::S
940 BySelf (imports ✖): std::S
941 "#]],
942 );
943 }
944
945 #[test]
946 fn different_crate_renamed() {
947 check_found_path(
948 r#"
949//- /main.rs crate:main deps:std
950extern crate std as std_renamed;
951$0
952//- /std.rs crate:std
953pub struct S;
954 "#,
955 "std_renamed::S",
956 expect![[r#"
957 Plain (imports ✔): std_renamed::S
958 Plain (imports ✖): std_renamed::S
959 ByCrate(imports ✔): std_renamed::S
960 ByCrate(imports ✖): std_renamed::S
961 BySelf (imports ✔): std_renamed::S
962 BySelf (imports ✖): std_renamed::S
963 "#]],
964 );
965 }
966
967 #[test]
968 fn partially_imported() {
969 cov_mark::check!(partially_imported);
970 check_found_path(
973 r#"
974//- /main.rs crate:main deps:syntax
975
976use syntax::ast;
977$0
978
979//- /lib.rs crate:syntax
980pub mod ast {
981 pub enum ModuleItem {
982 A, B, C,
983 }
984}
985 "#,
986 "syntax::ast::ModuleItem",
987 expect![[r#"
988 Plain (imports ✔): ast::ModuleItem
989 Plain (imports ✖): syntax::ast::ModuleItem
990 ByCrate(imports ✔): crate::ast::ModuleItem
991 ByCrate(imports ✖): syntax::ast::ModuleItem
992 BySelf (imports ✔): self::ast::ModuleItem
993 BySelf (imports ✖): syntax::ast::ModuleItem
994 "#]],
995 );
996
997 check_found_path(
998 r#"
999//- /main.rs crate:main deps:syntax
1000$0
1001
1002//- /lib.rs crate:syntax
1003pub mod ast {
1004 pub enum ModuleItem {
1005 A, B, C,
1006 }
1007}
1008 "#,
1009 "syntax::ast::ModuleItem",
1010 expect![[r#"
1011 Plain (imports ✔): syntax::ast::ModuleItem
1012 Plain (imports ✖): syntax::ast::ModuleItem
1013 ByCrate(imports ✔): syntax::ast::ModuleItem
1014 ByCrate(imports ✖): syntax::ast::ModuleItem
1015 BySelf (imports ✔): syntax::ast::ModuleItem
1016 BySelf (imports ✖): syntax::ast::ModuleItem
1017 "#]],
1018 );
1019 }
1020
1021 #[test]
1022 fn partially_imported_with_prefer_absolute() {
1023 cov_mark::check!(partially_imported);
1024 check_found_path_absolute(
1029 r#"
1030//- /main.rs crate:main deps:syntax
1031
1032use syntax::ast;
1033$0
1034
1035//- /lib.rs crate:syntax
1036pub mod ast {
1037 pub enum ModuleItem {
1038 A, B, C,
1039 }
1040}
1041 "#,
1042 "syntax::ast::ModuleItem",
1043 expect![[r#"
1044 Plain (imports ✔): ast::ModuleItem
1045 Plain (imports ✖): ::syntax::ast::ModuleItem
1046 ByCrate(imports ✔): crate::ast::ModuleItem
1047 ByCrate(imports ✖): ::syntax::ast::ModuleItem
1048 BySelf (imports ✔): self::ast::ModuleItem
1049 BySelf (imports ✖): ::syntax::ast::ModuleItem
1050 "#]],
1051 );
1052 }
1053
1054 #[test]
1055 fn same_crate_reexport() {
1056 check_found_path(
1057 r#"
1058mod bar {
1059 mod foo { pub(crate) struct S; }
1060 pub(crate) use foo::*;
1061}
1062$0
1063 "#,
1064 "bar::S",
1065 expect![[r#"
1066 Plain (imports ✔): bar::S
1067 Plain (imports ✖): bar::S
1068 ByCrate(imports ✔): crate::bar::S
1069 ByCrate(imports ✖): crate::bar::S
1070 BySelf (imports ✔): self::bar::S
1071 BySelf (imports ✖): self::bar::S
1072 "#]],
1073 );
1074 }
1075
1076 #[test]
1077 fn same_crate_reexport_rename() {
1078 check_found_path(
1079 r#"
1080mod bar {
1081 mod foo { pub(crate) struct S; }
1082 pub(crate) use foo::S as U;
1083}
1084$0
1085 "#,
1086 "bar::U",
1087 expect![[r#"
1088 Plain (imports ✔): bar::U
1089 Plain (imports ✖): bar::U
1090 ByCrate(imports ✔): crate::bar::U
1091 ByCrate(imports ✖): crate::bar::U
1092 BySelf (imports ✔): self::bar::U
1093 BySelf (imports ✖): self::bar::U
1094 "#]],
1095 );
1096 }
1097
1098 #[test]
1099 fn different_crate_reexport() {
1100 check_found_path(
1101 r#"
1102//- /main.rs crate:main deps:std
1103$0
1104//- /std.rs crate:std deps:core
1105pub use core::S;
1106//- /core.rs crate:core
1107pub struct S;
1108 "#,
1109 "std::S",
1110 expect![[r#"
1111 Plain (imports ✔): std::S
1112 Plain (imports ✖): std::S
1113 ByCrate(imports ✔): std::S
1114 ByCrate(imports ✖): std::S
1115 BySelf (imports ✔): std::S
1116 BySelf (imports ✖): std::S
1117 "#]],
1118 );
1119 }
1120
1121 #[test]
1122 fn prelude() {
1123 check_found_path(
1124 r#"
1125//- /main.rs edition:2018 crate:main deps:std
1126$0
1127//- /std.rs crate:std
1128pub mod prelude {
1129 pub mod rust_2018 {
1130 pub struct S;
1131 }
1132}
1133 "#,
1134 "S",
1135 expect![[r#"
1136 Plain (imports ✔): S
1137 Plain (imports ✖): S
1138 ByCrate(imports ✔): S
1139 ByCrate(imports ✖): S
1140 BySelf (imports ✔): S
1141 BySelf (imports ✖): S
1142 "#]],
1143 );
1144 }
1145
1146 #[test]
1147 fn shadowed_prelude() {
1148 check_found_path(
1149 r#"
1150//- /main.rs crate:main deps:std
1151struct S;
1152$0
1153//- /std.rs crate:std
1154pub mod prelude {
1155 pub mod rust_2018 {
1156 pub struct S;
1157 }
1158}
1159"#,
1160 "std::prelude::rust_2018::S",
1161 expect![[r#"
1162 Plain (imports ✔): std::prelude::rust_2018::S
1163 Plain (imports ✖): std::prelude::rust_2018::S
1164 ByCrate(imports ✔): std::prelude::rust_2018::S
1165 ByCrate(imports ✖): std::prelude::rust_2018::S
1166 BySelf (imports ✔): std::prelude::rust_2018::S
1167 BySelf (imports ✖): std::prelude::rust_2018::S
1168 "#]],
1169 );
1170 }
1171
1172 #[test]
1173 fn imported_prelude() {
1174 check_found_path(
1175 r#"
1176//- /main.rs edition:2018 crate:main deps:std
1177use S;
1178$0
1179//- /std.rs crate:std
1180pub mod prelude {
1181 pub mod rust_2018 {
1182 pub struct S;
1183 }
1184}
1185"#,
1186 "S",
1187 expect![[r#"
1188 Plain (imports ✔): S
1189 Plain (imports ✖): S
1190 ByCrate(imports ✔): crate::S
1191 ByCrate(imports ✖): S
1192 BySelf (imports ✔): self::S
1193 BySelf (imports ✖): S
1194 "#]],
1195 );
1196 }
1197
1198 #[test]
1199 fn enum_variant_from_prelude() {
1200 let code = r#"
1201//- /main.rs edition:2018 crate:main deps:std
1202$0
1203//- /std.rs crate:std
1204pub mod prelude {
1205 pub mod rust_2018 {
1206 pub enum Option<T> { Some(T), None }
1207 pub use Option::*;
1208 }
1209}
1210 "#;
1211 check_found_path(
1212 code,
1213 "None",
1214 expect![[r#"
1215 Plain (imports ✔): None
1216 Plain (imports ✖): None
1217 ByCrate(imports ✔): None
1218 ByCrate(imports ✖): None
1219 BySelf (imports ✔): None
1220 BySelf (imports ✖): None
1221 "#]],
1222 );
1223 check_found_path(
1224 code,
1225 "Some",
1226 expect![[r#"
1227 Plain (imports ✔): Some
1228 Plain (imports ✖): Some
1229 ByCrate(imports ✔): Some
1230 ByCrate(imports ✖): Some
1231 BySelf (imports ✔): Some
1232 BySelf (imports ✖): Some
1233 "#]],
1234 );
1235 }
1236
1237 #[test]
1238 fn shortest_path() {
1239 check_found_path(
1240 r#"
1241//- /main.rs
1242pub mod foo;
1243pub mod baz;
1244struct S;
1245$0
1246//- /foo.rs
1247pub mod bar { pub struct S; }
1248//- /baz.rs
1249pub use crate::foo::bar::S;
1250 "#,
1251 "baz::S",
1252 expect![[r#"
1253 Plain (imports ✔): baz::S
1254 Plain (imports ✖): baz::S
1255 ByCrate(imports ✔): crate::baz::S
1256 ByCrate(imports ✖): crate::baz::S
1257 BySelf (imports ✔): self::baz::S
1258 BySelf (imports ✖): self::baz::S
1259 "#]],
1260 );
1261 }
1262
1263 #[test]
1264 fn discount_private_imports() {
1265 cov_mark::check!(discount_private_imports);
1266 check_found_path(
1267 r#"
1268//- /main.rs
1269mod foo;
1270pub mod bar { pub struct S; }
1271use bar::S;
1272//- /foo.rs
1273$0
1274 "#,
1275 "crate::bar::S",
1277 expect![[r#"
1278 Plain (imports ✔): crate::bar::S
1279 Plain (imports ✖): crate::bar::S
1280 ByCrate(imports ✔): crate::bar::S
1281 ByCrate(imports ✖): crate::bar::S
1282 BySelf (imports ✔): crate::bar::S
1283 BySelf (imports ✖): crate::bar::S
1284 "#]],
1285 );
1286 }
1287
1288 #[test]
1289 fn explicit_private_imports_crate() {
1290 check_found_path(
1291 r#"
1292//- /main.rs
1293mod foo;
1294pub mod bar { pub struct S; }
1295pub(crate) use bar::S;
1296//- /foo.rs
1297$0
1298 "#,
1299 "crate::S",
1300 expect![[r#"
1301 Plain (imports ✔): crate::S
1302 Plain (imports ✖): crate::S
1303 ByCrate(imports ✔): crate::S
1304 ByCrate(imports ✖): crate::S
1305 BySelf (imports ✔): crate::S
1306 BySelf (imports ✖): crate::S
1307 "#]],
1308 );
1309 }
1310
1311 #[test]
1312 fn explicit_private_imports() {
1313 cov_mark::check!(explicit_private_imports);
1314 check_found_path(
1315 r#"
1316//- /main.rs
1317pub mod bar {
1318 mod foo;
1319 pub mod baz { pub struct S; }
1320 pub(self) use baz::S;
1321}
1322
1323//- /bar/foo.rs
1324$0
1325 "#,
1326 "super::S",
1327 expect![[r#"
1328 Plain (imports ✔): super::S
1329 Plain (imports ✖): super::S
1330 ByCrate(imports ✔): crate::bar::S
1331 ByCrate(imports ✖): crate::bar::S
1332 BySelf (imports ✔): super::S
1333 BySelf (imports ✖): super::S
1334 "#]],
1335 );
1336 }
1337
1338 #[test]
1339 fn import_cycle() {
1340 check_found_path(
1341 r#"
1342//- /main.rs
1343pub mod foo;
1344pub mod bar;
1345pub mod baz;
1346//- /bar.rs
1347$0
1348//- /foo.rs
1349pub use super::baz;
1350pub struct S;
1351//- /baz.rs
1352pub use super::foo;
1353 "#,
1354 "crate::foo::S",
1355 expect![[r#"
1356 Plain (imports ✔): crate::foo::S
1357 Plain (imports ✖): crate::foo::S
1358 ByCrate(imports ✔): crate::foo::S
1359 ByCrate(imports ✖): crate::foo::S
1360 BySelf (imports ✔): crate::foo::S
1361 BySelf (imports ✖): crate::foo::S
1362 "#]],
1363 );
1364 }
1365
1366 #[test]
1367 fn prefer_std_paths_over_alloc() {
1368 check_found_path(
1369 r#"
1370//- /main.rs crate:main deps:alloc,std
1371$0
1372
1373//- /std.rs crate:std deps:alloc
1374pub mod sync {
1375 pub use alloc::sync::Arc;
1376}
1377
1378//- /zzz.rs crate:alloc
1379pub mod sync {
1380 pub struct Arc;
1381}
1382 "#,
1383 "std::sync::Arc",
1384 expect![[r#"
1385 Plain (imports ✔): std::sync::Arc
1386 Plain (imports ✖): std::sync::Arc
1387 ByCrate(imports ✔): std::sync::Arc
1388 ByCrate(imports ✖): std::sync::Arc
1389 BySelf (imports ✔): std::sync::Arc
1390 BySelf (imports ✖): std::sync::Arc
1391 "#]],
1392 );
1393 }
1394 #[test]
1395 fn prefer_core_paths_over_std_for_mod_reexport() {
1396 check_found_path_prefer_no_std(
1397 r#"
1398//- /main.rs crate:main deps:core,std
1399
1400$0
1401
1402//- /stdlib.rs crate:std deps:core
1403
1404pub use core::pin;
1405
1406//- /corelib.rs crate:core
1407
1408pub mod pin {
1409 pub struct Pin;
1410}
1411 "#,
1412 "std::pin::Pin",
1413 expect![[r#"
1414 Plain (imports ✔): core::pin::Pin
1415 Plain (imports ✖): core::pin::Pin
1416 ByCrate(imports ✔): core::pin::Pin
1417 ByCrate(imports ✖): core::pin::Pin
1418 BySelf (imports ✔): core::pin::Pin
1419 BySelf (imports ✖): core::pin::Pin
1420 "#]],
1421 );
1422 }
1423
1424 #[test]
1425 fn prefer_core_paths_over_std() {
1426 check_found_path_prefer_no_std(
1427 r#"
1428//- /main.rs crate:main deps:core,std
1429
1430$0
1431
1432//- /std.rs crate:std deps:core
1433
1434pub mod fmt {
1435 pub use core::fmt::Error;
1436}
1437
1438//- /zzz.rs crate:core
1439
1440pub mod fmt {
1441 pub struct Error;
1442}
1443 "#,
1444 "core::fmt::Error",
1445 expect![[r#"
1446 Plain (imports ✔): core::fmt::Error
1447 Plain (imports ✖): core::fmt::Error
1448 ByCrate(imports ✔): core::fmt::Error
1449 ByCrate(imports ✖): core::fmt::Error
1450 BySelf (imports ✔): core::fmt::Error
1451 BySelf (imports ✖): core::fmt::Error
1452 "#]],
1453 );
1454 check_found_path(
1455 r#"
1456//- /main.rs crate:main deps:core,std
1457#![no_std]
1458
1459$0
1460
1461//- /std.rs crate:std deps:core
1462
1463pub mod fmt {
1464 pub use core::fmt::Error;
1465}
1466
1467//- /zzz.rs crate:core
1468
1469pub mod fmt {
1470 pub struct Error;
1471}
1472 "#,
1473 "core::fmt::Error",
1474 expect![[r#"
1475 Plain (imports ✔): core::fmt::Error
1476 Plain (imports ✖): core::fmt::Error
1477 ByCrate(imports ✔): core::fmt::Error
1478 ByCrate(imports ✖): core::fmt::Error
1479 BySelf (imports ✔): core::fmt::Error
1480 BySelf (imports ✖): core::fmt::Error
1481 "#]],
1482 );
1483
1484 check_found_path(
1486 r#"
1487//- /main.rs crate:main deps:core,std
1488#![cfg_attr(not(test), no_std)]
1489
1490$0
1491
1492//- /std.rs crate:std deps:core
1493
1494pub mod fmt {
1495 pub use core::fmt::Error;
1496}
1497
1498//- /zzz.rs crate:core
1499
1500pub mod fmt {
1501 pub struct Error;
1502}
1503 "#,
1504 "core::fmt::Error",
1505 expect![[r#"
1506 Plain (imports ✔): core::fmt::Error
1507 Plain (imports ✖): core::fmt::Error
1508 ByCrate(imports ✔): core::fmt::Error
1509 ByCrate(imports ✖): core::fmt::Error
1510 BySelf (imports ✔): core::fmt::Error
1511 BySelf (imports ✖): core::fmt::Error
1512 "#]],
1513 );
1514 }
1515
1516 #[test]
1517 fn prefer_alloc_paths_over_std() {
1518 check_found_path(
1519 r#"
1520//- /main.rs crate:main deps:alloc,std
1521#![no_std]
1522
1523extern crate alloc;
1524
1525$0
1526
1527//- /std.rs crate:std deps:alloc
1528
1529pub mod sync {
1530 pub use alloc::sync::Arc;
1531}
1532
1533//- /zzz.rs crate:alloc
1534
1535pub mod sync {
1536 pub struct Arc;
1537}
1538 "#,
1539 "alloc::sync::Arc",
1540 expect![[r#"
1541 Plain (imports ✔): alloc::sync::Arc
1542 Plain (imports ✖): alloc::sync::Arc
1543 ByCrate(imports ✔): alloc::sync::Arc
1544 ByCrate(imports ✖): alloc::sync::Arc
1545 BySelf (imports ✔): alloc::sync::Arc
1546 BySelf (imports ✖): alloc::sync::Arc
1547 "#]],
1548 );
1549 }
1550
1551 #[test]
1552 fn prefer_shorter_paths_if_not_alloc() {
1553 check_found_path(
1554 r#"
1555//- /main.rs crate:main deps:megaalloc,std
1556$0
1557
1558//- /std.rs crate:std deps:megaalloc
1559pub mod sync {
1560 pub use megaalloc::sync::Arc;
1561}
1562
1563//- /zzz.rs crate:megaalloc
1564pub struct Arc;
1565 "#,
1566 "megaalloc::Arc",
1567 expect![[r#"
1568 Plain (imports ✔): megaalloc::Arc
1569 Plain (imports ✖): megaalloc::Arc
1570 ByCrate(imports ✔): megaalloc::Arc
1571 ByCrate(imports ✖): megaalloc::Arc
1572 BySelf (imports ✔): megaalloc::Arc
1573 BySelf (imports ✖): megaalloc::Arc
1574 "#]],
1575 );
1576 }
1577
1578 #[test]
1579 fn builtins_are_in_scope() {
1580 let code = r#"
1581$0
1582
1583pub mod primitive {
1584 pub use u8;
1585}
1586 "#;
1587 check_found_path(
1588 code,
1589 "u8",
1590 expect![[r#"
1591 Plain (imports ✔): u8
1592 Plain (imports ✖): u8
1593 ByCrate(imports ✔): u8
1594 ByCrate(imports ✖): u8
1595 BySelf (imports ✔): u8
1596 BySelf (imports ✖): u8
1597 "#]],
1598 );
1599 check_found_path(
1600 code,
1601 "u16",
1602 expect![[r#"
1603 Plain (imports ✔): u16
1604 Plain (imports ✖): u16
1605 ByCrate(imports ✔): u16
1606 ByCrate(imports ✖): u16
1607 BySelf (imports ✔): u16
1608 BySelf (imports ✖): u16
1609 "#]],
1610 );
1611 }
1612
1613 #[test]
1614 fn inner_items() {
1615 check_found_path(
1616 r#"
1617fn main() {
1618 struct Inner {}
1619 $0
1620}
1621 "#,
1622 "Inner",
1623 expect![[r#"
1624 Plain (imports ✔): Inner
1625 Plain (imports ✖): Inner
1626 ByCrate(imports ✔): Inner
1627 ByCrate(imports ✖): Inner
1628 BySelf (imports ✔): Inner
1629 BySelf (imports ✖): Inner
1630 "#]],
1631 );
1632 }
1633
1634 #[test]
1635 fn inner_items_from_outer_scope() {
1636 check_found_path(
1637 r#"
1638fn main() {
1639 struct Struct {}
1640 {
1641 $0
1642 }
1643}
1644 "#,
1645 "Struct",
1646 expect![[r#"
1647 Plain (imports ✔): Struct
1648 Plain (imports ✖): Struct
1649 ByCrate(imports ✔): Struct
1650 ByCrate(imports ✖): Struct
1651 BySelf (imports ✔): Struct
1652 BySelf (imports ✖): Struct
1653 "#]],
1654 );
1655 }
1656
1657 #[test]
1658 fn inner_items_from_inner_module() {
1659 check_found_path(
1660 r#"
1661fn main() {
1662 mod module {
1663 pub struct Struct {}
1664 }
1665 {
1666 $0
1667 }
1668}
1669 "#,
1670 "module::Struct",
1671 expect![[r#"
1672 Plain (imports ✔): module::Struct
1673 Plain (imports ✖): module::Struct
1674 ByCrate(imports ✔): module::Struct
1675 ByCrate(imports ✖): module::Struct
1676 BySelf (imports ✔): module::Struct
1677 BySelf (imports ✖): module::Struct
1678 "#]],
1679 );
1680 }
1681
1682 #[test]
1683 fn outer_items_with_inner_items_present() {
1684 check_found_path(
1685 r#"
1686mod module {
1687 pub struct CompleteMe;
1688}
1689
1690fn main() {
1691 fn inner() {}
1692 $0
1693}
1694 "#,
1695 "module::CompleteMe",
1696 expect![[r#"
1697 Plain (imports ✔): module::CompleteMe
1698 Plain (imports ✖): module::CompleteMe
1699 ByCrate(imports ✔): crate::module::CompleteMe
1700 ByCrate(imports ✖): crate::module::CompleteMe
1701 BySelf (imports ✔): self::module::CompleteMe
1702 BySelf (imports ✖): self::module::CompleteMe
1703 "#]],
1704 )
1705 }
1706
1707 #[test]
1708 fn from_inside_module() {
1709 check_found_path(
1710 r#"
1711mod baz {
1712 pub struct Foo {}
1713}
1714
1715mod bar {
1716 fn bar() {
1717 $0
1718 }
1719}
1720 "#,
1721 "crate::baz::Foo",
1722 expect![[r#"
1723 Plain (imports ✔): crate::baz::Foo
1724 Plain (imports ✖): crate::baz::Foo
1725 ByCrate(imports ✔): crate::baz::Foo
1726 ByCrate(imports ✖): crate::baz::Foo
1727 BySelf (imports ✔): crate::baz::Foo
1728 BySelf (imports ✖): crate::baz::Foo
1729 "#]],
1730 )
1731 }
1732
1733 #[test]
1734 fn from_inside_module2() {
1735 check_found_path(
1736 r#"
1737mod qux {
1738 pub mod baz {
1739 pub struct Foo {}
1740 }
1741
1742 mod bar {
1743 fn bar() {
1744 $0;
1745 }
1746 }
1747}
1748
1749 "#,
1750 "crate::qux::baz::Foo",
1751 expect![[r#"
1752 Plain (imports ✔): super::baz::Foo
1753 Plain (imports ✖): super::baz::Foo
1754 ByCrate(imports ✔): crate::qux::baz::Foo
1755 ByCrate(imports ✖): crate::qux::baz::Foo
1756 BySelf (imports ✔): super::baz::Foo
1757 BySelf (imports ✖): super::baz::Foo
1758 "#]],
1759 )
1760 }
1761
1762 #[test]
1763 fn from_inside_module_with_inner_items() {
1764 check_found_path(
1765 r#"
1766mod baz {
1767 pub struct Foo {}
1768}
1769
1770mod bar {
1771 fn bar() {
1772 fn inner() {}
1773 $0
1774 }
1775}
1776 "#,
1777 "crate::baz::Foo",
1778 expect![[r#"
1779 Plain (imports ✔): crate::baz::Foo
1780 Plain (imports ✖): crate::baz::Foo
1781 ByCrate(imports ✔): crate::baz::Foo
1782 ByCrate(imports ✖): crate::baz::Foo
1783 BySelf (imports ✔): crate::baz::Foo
1784 BySelf (imports ✖): crate::baz::Foo
1785 "#]],
1786 )
1787 }
1788
1789 #[test]
1790 fn recursive_pub_mod_reexport() {
1791 check_found_path(
1792 r#"
1793fn main() {
1794 let _ = 22_i32.as_name$0();
1795}
1796
1797pub mod name {
1798 pub trait AsName {
1799 fn as_name(&self) -> String;
1800 }
1801 impl AsName for i32 {
1802 fn as_name(&self) -> String {
1803 format!("Name: {}", self)
1804 }
1805 }
1806 pub use crate::name;
1807}
1808"#,
1809 "name::AsName",
1810 expect![[r#"
1811 Plain (imports ✔): name::AsName
1812 Plain (imports ✖): name::AsName
1813 ByCrate(imports ✔): crate::name::AsName
1814 ByCrate(imports ✖): crate::name::AsName
1815 BySelf (imports ✔): self::name::AsName
1816 BySelf (imports ✖): self::name::AsName
1817 "#]],
1818 );
1819 }
1820
1821 #[test]
1822 fn extern_crate() {
1823 check_found_path(
1824 r#"
1825//- /main.rs crate:main deps:dep
1826$0
1827//- /dep.rs crate:dep
1828"#,
1829 "dep",
1830 expect![[r#"
1831 Plain (imports ✔): dep
1832 Plain (imports ✖): dep
1833 ByCrate(imports ✔): dep
1834 ByCrate(imports ✖): dep
1835 BySelf (imports ✔): dep
1836 BySelf (imports ✖): dep
1837 "#]],
1838 );
1839
1840 check_found_path(
1841 r#"
1842//- /main.rs crate:main deps:dep
1843fn f() {
1844 fn inner() {}
1845 $0
1846}
1847//- /dep.rs crate:dep
1848"#,
1849 "dep",
1850 expect![[r#"
1851 Plain (imports ✔): dep
1852 Plain (imports ✖): dep
1853 ByCrate(imports ✔): dep
1854 ByCrate(imports ✖): dep
1855 BySelf (imports ✔): dep
1856 BySelf (imports ✖): dep
1857 "#]],
1858 );
1859 }
1860
1861 #[test]
1862 fn prelude_with_inner_items() {
1863 check_found_path(
1864 r#"
1865//- /main.rs edition:2018 crate:main deps:std
1866fn f() {
1867 fn inner() {}
1868 $0
1869}
1870//- /std.rs crate:std
1871pub mod prelude {
1872 pub mod rust_2018 {
1873 pub enum Option { None }
1874 pub use Option::*;
1875 }
1876}
1877 "#,
1878 "None",
1879 expect![[r#"
1880 Plain (imports ✔): None
1881 Plain (imports ✖): None
1882 ByCrate(imports ✔): None
1883 ByCrate(imports ✖): None
1884 BySelf (imports ✔): None
1885 BySelf (imports ✖): None
1886 "#]],
1887 );
1888 }
1889
1890 #[test]
1891 fn different_crate_renamed_through_dep() {
1892 check_found_path(
1893 r#"
1894//- /main.rs crate:main deps:intermediate
1895$0
1896//- /intermediate.rs crate:intermediate deps:std
1897pub extern crate std as std_renamed;
1898//- /std.rs crate:std
1899pub struct S;
1900 "#,
1901 "intermediate::std_renamed::S",
1902 expect![[r#"
1903 Plain (imports ✔): intermediate::std_renamed::S
1904 Plain (imports ✖): intermediate::std_renamed::S
1905 ByCrate(imports ✔): intermediate::std_renamed::S
1906 ByCrate(imports ✖): intermediate::std_renamed::S
1907 BySelf (imports ✔): intermediate::std_renamed::S
1908 BySelf (imports ✖): intermediate::std_renamed::S
1909 "#]],
1910 );
1911 }
1912
1913 #[test]
1914 fn different_crate_doc_hidden() {
1915 check_found_path(
1916 r#"
1917//- /main.rs crate:main deps:intermediate
1918$0
1919//- /intermediate.rs crate:intermediate deps:std
1920#[doc(hidden)]
1921pub extern crate std;
1922pub extern crate std as longer;
1923//- /std.rs crate:std
1924pub struct S;
1925 "#,
1926 "intermediate::longer::S",
1927 expect![[r#"
1928 Plain (imports ✔): intermediate::longer::S
1929 Plain (imports ✖): intermediate::longer::S
1930 ByCrate(imports ✔): intermediate::longer::S
1931 ByCrate(imports ✖): intermediate::longer::S
1932 BySelf (imports ✔): intermediate::longer::S
1933 BySelf (imports ✖): intermediate::longer::S
1934 "#]],
1935 );
1936 }
1937
1938 #[test]
1939 fn respect_doc_hidden() {
1940 check_found_path(
1941 r#"
1942//- /main.rs crate:main deps:std,lazy_static
1943$0
1944//- /lazy_static.rs crate:lazy_static deps:core
1945#[doc(hidden)]
1946pub use core::ops::Deref as __Deref;
1947//- /std.rs crate:std deps:core
1948pub use core::ops;
1949//- /core.rs crate:core
1950pub mod ops {
1951 pub trait Deref {}
1952}
1953 "#,
1954 "std::ops::Deref",
1955 expect![[r#"
1956 Plain (imports ✔): std::ops::Deref
1957 Plain (imports ✖): std::ops::Deref
1958 ByCrate(imports ✔): std::ops::Deref
1959 ByCrate(imports ✖): std::ops::Deref
1960 BySelf (imports ✔): std::ops::Deref
1961 BySelf (imports ✖): std::ops::Deref
1962 "#]],
1963 );
1964 }
1965
1966 #[test]
1967 fn respect_unstable_modules() {
1968 check_found_path_prefer_no_std_allow_unstable(
1969 r#"
1970//- /main.rs crate:main deps:std,core
1971extern crate std;
1972$0
1973//- /longer.rs crate:std deps:core
1974pub mod error {
1975 pub use core::error::Error;
1976}
1977//- /core.rs crate:core
1978pub mod error {
1979 #![unstable(feature = "error_in_core", issue = "103765")]
1980 pub trait Error {}
1981}
1982"#,
1983 "std::error::Error",
1984 expect![[r#"
1985 Plain (imports ✔): std::error::Error
1986 Plain (imports ✖): std::error::Error
1987 ByCrate(imports ✔): std::error::Error
1988 ByCrate(imports ✖): std::error::Error
1989 BySelf (imports ✔): std::error::Error
1990 BySelf (imports ✖): std::error::Error
1991 "#]],
1992 );
1993 }
1994
1995 #[test]
1996 fn respects_prelude_setting() {
1997 let ra_fixture = r#"
1998//- /main.rs crate:main deps:krate
1999$0
2000//- /krate.rs crate:krate
2001pub mod prelude {
2002 pub use crate::foo::*;
2003}
2004
2005pub mod foo {
2006 pub struct Foo;
2007}
2008"#;
2009 check_found_path(
2010 ra_fixture,
2011 "krate::foo::Foo",
2012 expect![[r#"
2013 Plain (imports ✔): krate::foo::Foo
2014 Plain (imports ✖): krate::foo::Foo
2015 ByCrate(imports ✔): krate::foo::Foo
2016 ByCrate(imports ✖): krate::foo::Foo
2017 BySelf (imports ✔): krate::foo::Foo
2018 BySelf (imports ✖): krate::foo::Foo
2019 "#]],
2020 );
2021 check_found_path_prelude(
2022 ra_fixture,
2023 "krate::prelude::Foo",
2024 expect![[r#"
2025 Plain (imports ✔): krate::prelude::Foo
2026 Plain (imports ✖): krate::prelude::Foo
2027 ByCrate(imports ✔): krate::prelude::Foo
2028 ByCrate(imports ✖): krate::prelude::Foo
2029 BySelf (imports ✔): krate::prelude::Foo
2030 BySelf (imports ✖): krate::prelude::Foo
2031 "#]],
2032 );
2033 }
2034
2035 #[test]
2036 fn respects_absolute_setting() {
2037 let ra_fixture = r#"
2038//- /main.rs crate:main deps:krate
2039$0
2040//- /krate.rs crate:krate
2041pub mod foo {
2042 pub struct Foo;
2043}
2044"#;
2045 check_found_path(
2046 ra_fixture,
2047 "krate::foo::Foo",
2048 expect![[r#"
2049 Plain (imports ✔): krate::foo::Foo
2050 Plain (imports ✖): krate::foo::Foo
2051 ByCrate(imports ✔): krate::foo::Foo
2052 ByCrate(imports ✖): krate::foo::Foo
2053 BySelf (imports ✔): krate::foo::Foo
2054 BySelf (imports ✖): krate::foo::Foo
2055 "#]],
2056 );
2057
2058 check_found_path_absolute(
2059 ra_fixture,
2060 "krate::foo::Foo",
2061 expect![[r#"
2062 Plain (imports ✔): ::krate::foo::Foo
2063 Plain (imports ✖): ::krate::foo::Foo
2064 ByCrate(imports ✔): ::krate::foo::Foo
2065 ByCrate(imports ✖): ::krate::foo::Foo
2066 BySelf (imports ✔): ::krate::foo::Foo
2067 BySelf (imports ✖): ::krate::foo::Foo
2068 "#]],
2069 );
2070 }
2071
2072 #[test]
2073 fn respect_segment_length() {
2074 check_found_path(
2075 r#"
2076//- /main.rs crate:main deps:petgraph
2077$0
2078//- /petgraph.rs crate:petgraph
2079pub mod graph {
2080 pub use crate::graph_impl::{
2081 NodeIndex
2082 };
2083}
2084
2085mod graph_impl {
2086 pub struct NodeIndex<Ix>(Ix);
2087}
2088
2089pub mod stable_graph {
2090 #[doc(no_inline)]
2091 pub use crate::graph::{NodeIndex};
2092}
2093
2094pub mod prelude {
2095 #[doc(no_inline)]
2096 pub use crate::graph::{NodeIndex};
2097}
2098"#,
2099 "petgraph::graph::NodeIndex",
2100 expect![[r#"
2101 Plain (imports ✔): petgraph::graph::NodeIndex
2102 Plain (imports ✖): petgraph::graph::NodeIndex
2103 ByCrate(imports ✔): petgraph::graph::NodeIndex
2104 ByCrate(imports ✖): petgraph::graph::NodeIndex
2105 BySelf (imports ✔): petgraph::graph::NodeIndex
2106 BySelf (imports ✖): petgraph::graph::NodeIndex
2107 "#]],
2108 );
2109 }
2110
2111 #[test]
2112 fn regression_17271() {
2113 check_found_path(
2114 r#"
2115//- /lib.rs crate:main
2116mod foo;
2117
2118//- /foo.rs
2119mod bar;
2120
2121pub fn b() {$0}
2122//- /foo/bar.rs
2123pub fn c() {}
2124"#,
2125 "bar::c",
2126 expect![[r#"
2127 Plain (imports ✔): bar::c
2128 Plain (imports ✖): bar::c
2129 ByCrate(imports ✔): crate::foo::bar::c
2130 ByCrate(imports ✖): crate::foo::bar::c
2131 BySelf (imports ✔): self::bar::c
2132 BySelf (imports ✖): self::bar::c
2133 "#]],
2134 );
2135 }
2136
2137 #[test]
2138 fn prefer_long_std_over_short_extern() {
2139 check_found_path(
2140 r#"
2141//- /lib.rs crate:main deps:futures_lite,std,core
2142$0
2143//- /futures_lite.rs crate:futures_lite deps:std,core
2144pub use crate::future::Future;
2145pub mod future {
2146 pub use core::future::Future;
2147}
2148//- /std.rs crate:std deps:core
2149pub use core::future;
2150//- /core.rs crate:core
2151pub mod future {
2152 pub trait Future {}
2153}
2154"#,
2155 "core::future::Future",
2156 expect![[r#"
2157 Plain (imports ✔): std::future::Future
2158 Plain (imports ✖): std::future::Future
2159 ByCrate(imports ✔): std::future::Future
2160 ByCrate(imports ✖): std::future::Future
2161 BySelf (imports ✔): std::future::Future
2162 BySelf (imports ✖): std::future::Future
2163 "#]],
2164 );
2165 }
2166}