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