1use either::Either;
2use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef};
3use ide_db::{
4 defs::{Definition, NameRefClass},
5 search::SearchScope,
6 source_change::SourceChangeBuilder,
7};
8use stdx::never;
9use syntax::{
10 AstNode, Direction, SyntaxNode, SyntaxToken, T,
11 ast::{self, Use, UseTree, VisibilityKind, make},
12};
13
14use crate::{
15 AssistId,
16 assist_context::{AssistContext, Assists},
17};
18
19pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
45 let star = ctx.find_token_syntax_at_offset(T![*])?;
46 let use_tree = star.parent().and_then(ast::UseTree::cast)?;
47 let use_item = star.parent_ancestors().find_map(ast::Use::cast)?;
48 let (parent, mod_path) = find_parent_and_path(&star)?;
49 let target_module = match ctx.sema.resolve_path(&mod_path)? {
50 PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it),
51 PathResolution::Def(ModuleDef::Adt(hir::Adt::Enum(e))) => Expandable::Enum(e),
52 _ => return None,
53 };
54
55 let current_scope = ctx.sema.scope(&star.parent()?)?;
56 let current_module = current_scope.module();
57
58 if !is_visible_from(ctx, &target_module, current_module) {
59 return None;
60 }
61
62 let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
63 acc.add(
64 AssistId::refactor_rewrite("expand_glob_import"),
65 "Expand glob import",
66 target.text_range(),
67 |builder| {
68 build_expanded_import(
69 ctx,
70 builder,
71 use_tree,
72 use_item,
73 target_module,
74 current_module,
75 false,
76 )
77 },
78 )
79}
80
81pub(crate) fn expand_glob_reexport(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
103 let star = ctx.find_token_syntax_at_offset(T![*])?;
104 let use_tree = star.parent().and_then(ast::UseTree::cast)?;
105 let use_item = star.parent_ancestors().find_map(ast::Use::cast)?;
106 let (parent, mod_path) = find_parent_and_path(&star)?;
107 let target_module = match ctx.sema.resolve_path(&mod_path)? {
108 PathResolution::Def(ModuleDef::Module(it)) => Expandable::Module(it),
109 PathResolution::Def(ModuleDef::Adt(hir::Adt::Enum(e))) => Expandable::Enum(e),
110 _ => return None,
111 };
112
113 let current_scope = ctx.sema.scope(&star.parent()?)?;
114 let current_module = current_scope.module();
115
116 if let VisibilityKind::PubSelf = get_export_visibility_kind(&use_item) {
117 return None;
118 }
119 if !is_visible_from(ctx, &target_module, current_module) {
120 return None;
121 }
122
123 let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
124 acc.add(
125 AssistId::refactor_rewrite("expand_glob_reexport"),
126 "Expand glob reexport",
127 target.text_range(),
128 |builder| {
129 build_expanded_import(
130 ctx,
131 builder,
132 use_tree,
133 use_item,
134 target_module,
135 current_module,
136 true,
137 )
138 },
139 )
140}
141
142fn build_expanded_import(
143 ctx: &AssistContext<'_>,
144 builder: &mut SourceChangeBuilder,
145 use_tree: UseTree,
146 use_item: Use,
147 target_module: Expandable,
148 current_module: Module,
149 reexport_public_items: bool,
150) {
151 let (must_be_pub, visible_from) = if !reexport_public_items {
152 (false, current_module)
153 } else {
154 match get_export_visibility_kind(&use_item) {
155 VisibilityKind::Pub => (true, current_module.krate(ctx.db()).root_module(ctx.db())),
156 VisibilityKind::PubCrate => {
157 (false, current_module.krate(ctx.db()).root_module(ctx.db()))
158 }
159 _ => (false, current_module),
160 }
161 };
162
163 let refs_in_target = find_refs_in_mod(ctx, target_module, visible_from, must_be_pub);
164 let imported_defs = find_imported_defs(ctx, use_item);
165
166 let filtered_defs =
167 if reexport_public_items { refs_in_target } else { refs_in_target.used_refs(ctx) };
168
169 let names_to_import = find_names_to_import(filtered_defs, imported_defs);
170 let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
171 let path = make::ext::ident_path(
172 &n.display(ctx.db(), current_module.krate(ctx.db()).edition(ctx.db())).to_string(),
173 );
174 make::use_tree(path, None, None, false)
175 }))
176 .clone_for_update();
177
178 let mut editor = builder.make_editor(use_tree.syntax());
179 match use_tree.star_token() {
180 Some(star) => {
181 let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1;
182 if needs_braces {
183 editor.replace(star, expanded.syntax())
184 } else {
185 let without_braces = expanded
186 .syntax()
187 .children_with_tokens()
188 .filter(|child| !matches!(child.kind(), T!['{'] | T!['}']))
189 .collect();
190 editor.replace_with_many(star, without_braces)
191 }
192 }
193 None => never!(),
194 }
195 builder.add_file_edits(ctx.vfs_file_id(), editor);
196}
197
198fn get_export_visibility_kind(use_item: &Use) -> VisibilityKind {
199 use syntax::ast::HasVisibility as _;
200 match use_item.visibility() {
201 Some(vis) => match vis.kind() {
202 VisibilityKind::PubCrate => VisibilityKind::PubCrate,
203 VisibilityKind::Pub => VisibilityKind::Pub,
204 VisibilityKind::PubSelf => VisibilityKind::PubSelf,
205 VisibilityKind::In(_) => VisibilityKind::PubSelf,
207 VisibilityKind::PubSuper => VisibilityKind::PubSelf,
208 },
209 None => VisibilityKind::PubSelf,
210 }
211}
212
213enum Expandable {
214 Module(Module),
215 Enum(Enum),
216}
217
218fn find_parent_and_path(
219 star: &SyntaxToken,
220) -> Option<(Either<ast::UseTree, ast::UseTreeList>, ast::Path)> {
221 return star.parent_ancestors().find_map(|n| {
222 find_use_tree_list(n.clone())
223 .map(|(u, p)| (Either::Right(u), p))
224 .or_else(|| find_use_tree(n).map(|(u, p)| (Either::Left(u), p)))
225 });
226
227 fn find_use_tree_list(n: SyntaxNode) -> Option<(ast::UseTreeList, ast::Path)> {
228 let use_tree_list = ast::UseTreeList::cast(n)?;
229 let path = use_tree_list.parent_use_tree().path()?;
230 Some((use_tree_list, path))
231 }
232
233 fn find_use_tree(n: SyntaxNode) -> Option<(ast::UseTree, ast::Path)> {
234 let use_tree = ast::UseTree::cast(n)?;
235 let path = use_tree.path()?;
236 Some((use_tree, path))
237 }
238}
239
240fn def_is_referenced_in(def: Definition, ctx: &AssistContext<'_>) -> bool {
241 let search_scope = SearchScope::single_file(ctx.file_id());
242 def.usages(&ctx.sema).in_scope(&search_scope).at_least_one()
243}
244
245#[derive(Debug, Clone)]
246struct Ref {
247 visible_name: Name,
249 def: Definition,
250 is_pub: bool,
251}
252
253impl Ref {
254 fn from_scope_def(ctx: &AssistContext<'_>, name: Name, scope_def: ScopeDef) -> Option<Self> {
255 match scope_def {
256 ScopeDef::ModuleDef(def) => Some(Ref {
257 visible_name: name,
258 def: Definition::from(def),
259 is_pub: matches!(def.visibility(ctx.db()), hir::Visibility::Public),
260 }),
261 _ => None,
262 }
263 }
264}
265
266#[derive(Debug, Clone)]
267struct Refs(Vec<Ref>);
268
269impl Refs {
270 fn used_refs(&self, ctx: &AssistContext<'_>) -> Refs {
271 Refs(
272 self.0
273 .clone()
274 .into_iter()
275 .filter(|r| {
276 if let Definition::Trait(tr) = r.def
277 && tr.items(ctx.db()).into_iter().any(|ai| {
278 if let AssocItem::Function(f) = ai {
279 def_is_referenced_in(Definition::Function(f), ctx)
280 } else {
281 false
282 }
283 })
284 {
285 return true;
286 }
287
288 def_is_referenced_in(r.def, ctx)
289 })
290 .collect(),
291 )
292 }
293
294 fn filter_out_by_defs(&self, defs: Vec<Definition>) -> Refs {
295 Refs(self.0.clone().into_iter().filter(|r| !defs.contains(&r.def)).collect())
296 }
297}
298
299fn find_refs_in_mod(
300 ctx: &AssistContext<'_>,
301 expandable: Expandable,
302 visible_from: Module,
303 must_be_pub: bool,
304) -> Refs {
305 match expandable {
306 Expandable::Module(module) => {
307 let module_scope = module.scope(ctx.db(), Some(visible_from));
308 let refs = module_scope
309 .into_iter()
310 .filter_map(|(n, d)| Ref::from_scope_def(ctx, n, d))
311 .filter(|r| !must_be_pub || r.is_pub)
312 .collect();
313 Refs(refs)
314 }
315 Expandable::Enum(enm) => Refs(
316 enm.variants(ctx.db())
317 .into_iter()
318 .map(|v| Ref {
319 visible_name: v.name(ctx.db()),
320 def: Definition::Variant(v),
321 is_pub: true,
322 })
323 .collect(),
324 ),
325 }
326}
327
328fn is_visible_from(ctx: &AssistContext<'_>, expandable: &Expandable, from: Module) -> bool {
329 fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
330 match module.parent(ctx.db()) {
331 Some(parent) => {
332 module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
333 && is_mod_visible_from(ctx, parent, from)
334 }
335 None => true,
336 }
337 }
338
339 match expandable {
340 Expandable::Module(module) => match module.parent(ctx.db()) {
341 Some(parent) => {
342 module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
343 && is_mod_visible_from(ctx, parent, from)
344 }
345 None => true,
346 },
347 Expandable::Enum(enm) => {
348 let module = enm.module(ctx.db());
349 enm.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
350 && is_mod_visible_from(ctx, module, from)
351 }
352 }
353}
354
355fn find_imported_defs(ctx: &AssistContext<'_>, use_item: Use) -> Vec<Definition> {
370 [Direction::Prev, Direction::Next]
371 .into_iter()
372 .flat_map(|dir| {
373 use_item.syntax().siblings(dir.to_owned()).filter(|n| ast::Use::can_cast(n.kind()))
374 })
375 .flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
376 .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
377 NameRefClass::Definition(
378 def @ (Definition::Macro(_)
379 | Definition::Module(_)
380 | Definition::Function(_)
381 | Definition::Adt(_)
382 | Definition::Variant(_)
383 | Definition::Const(_)
384 | Definition::Static(_)
385 | Definition::Trait(_)
386 | Definition::TypeAlias(_)),
387 _,
388 ) => Some(def),
389 _ => None,
390 })
391 .collect()
392}
393
394fn find_names_to_import(refs_in_target: Refs, imported_defs: Vec<Definition>) -> Vec<Name> {
395 let final_refs = refs_in_target.filter_out_by_defs(imported_defs);
396 final_refs.0.iter().map(|r| r.visible_name.clone()).collect()
397}
398
399#[cfg(test)]
400mod tests {
401 use crate::tests::{check_assist, check_assist_not_applicable};
402
403 use super::*;
404
405 #[test]
406 fn expanding_glob_import() {
407 check_assist(
408 expand_glob_import,
409 r"
410mod foo {
411 pub struct Bar;
412 pub struct Baz;
413 pub struct Qux;
414
415 pub fn f() {}
416}
417
418use foo::*$0;
419
420fn qux(bar: Bar, baz: Baz) {
421 f();
422}
423",
424 r"
425mod foo {
426 pub struct Bar;
427 pub struct Baz;
428 pub struct Qux;
429
430 pub fn f() {}
431}
432
433use foo::{Bar, Baz, f};
434
435fn qux(bar: Bar, baz: Baz) {
436 f();
437}
438",
439 )
440 }
441
442 #[test]
443 fn expanding_glob_import_unused() {
444 check_assist(
445 expand_glob_import,
446 r"
447mod foo {
448 pub struct Bar;
449 pub struct Baz;
450 pub struct Qux;
451
452 pub fn f() {}
453}
454
455use foo::*$0;
456
457fn qux() {}
458",
459 r"
460mod foo {
461 pub struct Bar;
462 pub struct Baz;
463 pub struct Qux;
464
465 pub fn f() {}
466}
467
468use foo::{};
469
470fn qux() {}
471",
472 )
473 }
474
475 #[test]
476 fn expanding_glob_import_with_existing_explicit_names() {
477 check_assist(
478 expand_glob_import,
479 r"
480mod foo {
481 pub struct Bar;
482 pub struct Baz;
483 pub struct Qux;
484
485 pub fn f() {}
486}
487
488use foo::{*$0, f};
489
490fn qux(bar: Bar, baz: Baz) {
491 f();
492}
493",
494 r"
495mod foo {
496 pub struct Bar;
497 pub struct Baz;
498 pub struct Qux;
499
500 pub fn f() {}
501}
502
503use foo::{Bar, Baz, f};
504
505fn qux(bar: Bar, baz: Baz) {
506 f();
507}
508",
509 )
510 }
511
512 #[test]
513 fn expanding_glob_import_with_existing_uses_in_same_module() {
514 check_assist(
515 expand_glob_import,
516 r"
517mod foo {
518 pub struct Bar;
519 pub struct Baz;
520 pub struct Qux;
521
522 pub fn f() {}
523}
524
525use foo::Bar;
526use foo::{*$0, f};
527
528fn qux(bar: Bar, baz: Baz) {
529 f();
530}
531",
532 r"
533mod foo {
534 pub struct Bar;
535 pub struct Baz;
536 pub struct Qux;
537
538 pub fn f() {}
539}
540
541use foo::Bar;
542use foo::{Baz, f};
543
544fn qux(bar: Bar, baz: Baz) {
545 f();
546}
547",
548 )
549 }
550
551 #[test]
552 fn expanding_nested_glob_import() {
553 check_assist(
554 expand_glob_import,
555 r"
556mod foo {
557 pub mod bar {
558 pub struct Bar;
559 pub struct Baz;
560 pub struct Qux;
561
562 pub fn f() {}
563 }
564
565 pub mod baz {
566 pub fn g() {}
567 }
568}
569
570use foo::{bar::{*$0, f}, baz::*};
571
572fn qux(bar: Bar, baz: Baz) {
573 f();
574 g();
575}
576",
577 r"
578mod foo {
579 pub mod bar {
580 pub struct Bar;
581 pub struct Baz;
582 pub struct Qux;
583
584 pub fn f() {}
585 }
586
587 pub mod baz {
588 pub fn g() {}
589 }
590}
591
592use foo::{bar::{Bar, Baz, f}, baz::*};
593
594fn qux(bar: Bar, baz: Baz) {
595 f();
596 g();
597}
598",
599 );
600
601 check_assist(
602 expand_glob_import,
603 r"
604mod foo {
605 pub mod bar {
606 pub struct Bar;
607 pub struct Baz;
608 pub struct Qux;
609
610 pub fn f() {}
611 }
612
613 pub mod baz {
614 pub fn g() {}
615 }
616}
617
618use foo::{bar::{Bar, Baz, f}, baz::*$0};
619
620fn qux(bar: Bar, baz: Baz) {
621 f();
622 g();
623}
624",
625 r"
626mod foo {
627 pub mod bar {
628 pub struct Bar;
629 pub struct Baz;
630 pub struct Qux;
631
632 pub fn f() {}
633 }
634
635 pub mod baz {
636 pub fn g() {}
637 }
638}
639
640use foo::{bar::{Bar, Baz, f}, baz::g};
641
642fn qux(bar: Bar, baz: Baz) {
643 f();
644 g();
645}
646",
647 );
648
649 check_assist(
650 expand_glob_import,
651 r"
652mod foo {
653 pub mod bar {
654 pub struct Bar;
655 pub struct Baz;
656 pub struct Qux;
657
658 pub fn f() {}
659 }
660
661 pub mod baz {
662 pub fn g() {}
663
664 pub mod qux {
665 pub fn h() {}
666 pub fn m() {}
667
668 pub mod q {
669 pub fn j() {}
670 }
671 }
672 }
673}
674
675use foo::{
676 bar::{*, f},
677 baz::{g, qux::*$0}
678};
679
680fn qux(bar: Bar, baz: Baz) {
681 f();
682 g();
683 h();
684 q::j();
685}
686",
687 r"
688mod foo {
689 pub mod bar {
690 pub struct Bar;
691 pub struct Baz;
692 pub struct Qux;
693
694 pub fn f() {}
695 }
696
697 pub mod baz {
698 pub fn g() {}
699
700 pub mod qux {
701 pub fn h() {}
702 pub fn m() {}
703
704 pub mod q {
705 pub fn j() {}
706 }
707 }
708 }
709}
710
711use foo::{
712 bar::{*, f},
713 baz::{g, qux::{h, q}}
714};
715
716fn qux(bar: Bar, baz: Baz) {
717 f();
718 g();
719 h();
720 q::j();
721}
722",
723 );
724
725 check_assist(
726 expand_glob_import,
727 r"
728mod foo {
729 pub mod bar {
730 pub struct Bar;
731 pub struct Baz;
732 pub struct Qux;
733
734 pub fn f() {}
735 }
736
737 pub mod baz {
738 pub fn g() {}
739
740 pub mod qux {
741 pub fn h() {}
742 pub fn m() {}
743
744 pub mod q {
745 pub fn j() {}
746 }
747 }
748 }
749}
750
751use foo::{
752 bar::{*, f},
753 baz::{g, qux::{h, q::*$0}}
754};
755
756fn qux(bar: Bar, baz: Baz) {
757 f();
758 g();
759 h();
760 j();
761}
762",
763 r"
764mod foo {
765 pub mod bar {
766 pub struct Bar;
767 pub struct Baz;
768 pub struct Qux;
769
770 pub fn f() {}
771 }
772
773 pub mod baz {
774 pub fn g() {}
775
776 pub mod qux {
777 pub fn h() {}
778 pub fn m() {}
779
780 pub mod q {
781 pub fn j() {}
782 }
783 }
784 }
785}
786
787use foo::{
788 bar::{*, f},
789 baz::{g, qux::{h, q::j}}
790};
791
792fn qux(bar: Bar, baz: Baz) {
793 f();
794 g();
795 h();
796 j();
797}
798",
799 );
800
801 check_assist(
802 expand_glob_import,
803 r"
804mod foo {
805 pub mod bar {
806 pub struct Bar;
807 pub struct Baz;
808 pub struct Qux;
809
810 pub fn f() {}
811 }
812
813 pub mod baz {
814 pub fn g() {}
815
816 pub mod qux {
817 pub fn h() {}
818 pub fn m() {}
819
820 pub mod q {
821 pub fn j() {}
822 }
823 }
824 }
825}
826
827use foo::{
828 bar::{*, f},
829 baz::{g, qux::{q::j, *$0}}
830};
831
832fn qux(bar: Bar, baz: Baz) {
833 f();
834 g();
835 h();
836 j();
837}
838",
839 r"
840mod foo {
841 pub mod bar {
842 pub struct Bar;
843 pub struct Baz;
844 pub struct Qux;
845
846 pub fn f() {}
847 }
848
849 pub mod baz {
850 pub fn g() {}
851
852 pub mod qux {
853 pub fn h() {}
854 pub fn m() {}
855
856 pub mod q {
857 pub fn j() {}
858 }
859 }
860 }
861}
862
863use foo::{
864 bar::{*, f},
865 baz::{g, qux::{q::j, h}}
866};
867
868fn qux(bar: Bar, baz: Baz) {
869 f();
870 g();
871 h();
872 j();
873}
874",
875 );
876 }
877
878 #[test]
879 fn expanding_glob_import_with_macro_defs() {
880 check_assist(
881 expand_glob_import,
882 r#"
883//- /lib.rs crate:foo
884#[macro_export]
885macro_rules! bar {
886 () => ()
887}
888
889pub fn baz() {}
890
891//- /main.rs crate:main deps:foo
892use foo::*$0;
893
894fn main() {
895 bar!();
896 baz();
897}
898"#,
899 r#"
900use foo::{bar, baz};
901
902fn main() {
903 bar!();
904 baz();
905}
906"#,
907 );
908 }
909
910 #[test]
911 fn expanding_glob_import_with_trait_method_uses() {
912 check_assist(
913 expand_glob_import,
914 r"
915//- /lib.rs crate:foo
916pub trait Tr {
917 fn method(&self) {}
918}
919impl Tr for () {}
920
921//- /main.rs crate:main deps:foo
922use foo::*$0;
923
924fn main() {
925 ().method();
926}
927",
928 r"
929use foo::Tr;
930
931fn main() {
932 ().method();
933}
934",
935 );
936
937 check_assist(
938 expand_glob_import,
939 r"
940//- /lib.rs crate:foo
941pub trait Tr {
942 fn method(&self) {}
943}
944impl Tr for () {}
945
946pub trait Tr2 {
947 fn method2(&self) {}
948}
949impl Tr2 for () {}
950
951//- /main.rs crate:main deps:foo
952use foo::*$0;
953
954fn main() {
955 ().method();
956}
957",
958 r"
959use foo::Tr;
960
961fn main() {
962 ().method();
963}
964",
965 );
966 }
967
968 #[test]
969 fn expanding_is_not_applicable_if_target_module_is_not_accessible_from_current_scope() {
970 check_assist_not_applicable(
971 expand_glob_import,
972 r"
973mod foo {
974 mod bar {
975 pub struct Bar;
976 }
977}
978
979use foo::bar::*$0;
980
981fn baz(bar: Bar) {}
982",
983 );
984
985 check_assist_not_applicable(
986 expand_glob_import,
987 r"
988mod foo {
989 mod bar {
990 pub mod baz {
991 pub struct Baz;
992 }
993 }
994}
995
996use foo::bar::baz::*$0;
997
998fn qux(baz: Baz) {}
999",
1000 );
1001 }
1002
1003 #[test]
1004 fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
1005 check_assist_not_applicable(
1006 expand_glob_import,
1007 r"
1008 mod foo {
1009 pub struct Bar;
1010 pub struct Baz;
1011 pub struct Qux;
1012 }
1013
1014 use foo::Bar$0;
1015
1016 fn qux(bar: Bar, baz: Baz) {}
1017 ",
1018 )
1019 }
1020
1021 #[test]
1022 fn expanding_glob_import_single_nested_glob_only() {
1023 check_assist(
1024 expand_glob_import,
1025 r"
1026mod foo {
1027 pub struct Bar;
1028}
1029
1030use foo::{*$0};
1031
1032struct Baz {
1033 bar: Bar
1034}
1035",
1036 r"
1037mod foo {
1038 pub struct Bar;
1039}
1040
1041use foo::{Bar};
1042
1043struct Baz {
1044 bar: Bar
1045}
1046",
1047 );
1048 }
1049
1050 #[test]
1051 fn test_support_for_enums() {
1052 check_assist(
1053 expand_glob_import,
1054 r#"
1055mod foo {
1056 pub enum Foo {
1057 Bar,
1058 Baz,
1059 }
1060}
1061
1062use foo::Foo;
1063use foo::Foo::*$0;
1064
1065struct Strukt {
1066 bar: Foo,
1067}
1068
1069fn main() {
1070 let s: Strukt = Strukt { bar: Bar };
1071}"#,
1072 r#"
1073mod foo {
1074 pub enum Foo {
1075 Bar,
1076 Baz,
1077 }
1078}
1079
1080use foo::Foo;
1081use foo::Foo::Bar;
1082
1083struct Strukt {
1084 bar: Foo,
1085}
1086
1087fn main() {
1088 let s: Strukt = Strukt { bar: Bar };
1089}"#,
1090 )
1091 }
1092
1093 #[test]
1094 fn test_expanding_multiple_variants_at_once() {
1095 check_assist(
1096 expand_glob_import,
1097 r#"
1098mod foo {
1099 pub enum Foo {
1100 Bar,
1101 Baz,
1102 }
1103}
1104
1105mod abc {
1106 use super::foo;
1107 use super::foo::Foo::*$0;
1108
1109 struct Strukt {
1110 baz: foo::Foo,
1111 bar: foo::Foo,
1112 }
1113
1114 fn trying_calling() {
1115 let s: Strukt = Strukt { bar: Bar , baz : Baz };
1116 }
1117
1118}"#,
1119 r#"
1120mod foo {
1121 pub enum Foo {
1122 Bar,
1123 Baz,
1124 }
1125}
1126
1127mod abc {
1128 use super::foo;
1129 use super::foo::Foo::{Bar, Baz};
1130
1131 struct Strukt {
1132 baz: foo::Foo,
1133 bar: foo::Foo,
1134 }
1135
1136 fn trying_calling() {
1137 let s: Strukt = Strukt { bar: Bar , baz : Baz };
1138 }
1139
1140}"#,
1141 )
1142 }
1143
1144 #[test]
1145 fn expanding_glob_reexport() {
1146 check_assist(
1147 expand_glob_reexport,
1148 r"
1149mod foo {
1150 pub struct Bar;
1151 pub struct Baz;
1152 struct Qux;
1153
1154 pub fn f() {}
1155
1156 pub(crate) fn g() {}
1157 pub(self) fn h() {}
1158}
1159
1160pub use foo::*$0;
1161",
1162 r"
1163mod foo {
1164 pub struct Bar;
1165 pub struct Baz;
1166 struct Qux;
1167
1168 pub fn f() {}
1169
1170 pub(crate) fn g() {}
1171 pub(self) fn h() {}
1172}
1173
1174pub use foo::{Bar, Baz, f};
1175",
1176 )
1177 }
1178
1179 #[test]
1180 fn expanding_recursive_glob_reexport() {
1181 check_assist(
1182 expand_glob_reexport,
1183 r"
1184mod foo {
1185 pub use bar::*;
1186 mod bar {
1187 pub struct Bar;
1188 pub struct Baz;
1189 }
1190}
1191
1192pub use foo::*$0;
1193",
1194 r"
1195mod foo {
1196 pub use bar::*;
1197 mod bar {
1198 pub struct Bar;
1199 pub struct Baz;
1200 }
1201}
1202
1203pub use foo::{Bar, Baz};
1204",
1205 )
1206 }
1207
1208 #[test]
1209 fn expanding_reexport_is_not_applicable_for_private_import() {
1210 check_assist_not_applicable(
1211 expand_glob_reexport,
1212 r"
1213mod foo {
1214 pub struct Bar;
1215 pub struct Baz;
1216}
1217
1218use foo::*$0;
1219",
1220 );
1221 }
1222}