diff options
-rw-r--r-- | crates/assists/src/handlers/expand_glob_import.rs | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/crates/assists/src/handlers/expand_glob_import.rs b/crates/assists/src/handlers/expand_glob_import.rs index 0e80cde77..194fae63e 100644 --- a/crates/assists/src/handlers/expand_glob_import.rs +++ b/crates/assists/src/handlers/expand_glob_import.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use either::Either; | 1 | use either::Either; |
2 | use hir::{MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; | 2 | use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef}; |
3 | use ide_db::{ | 3 | use ide_db::{ |
4 | defs::{classify_name_ref, Definition, NameRefClass}, | 4 | defs::{classify_name_ref, Definition, NameRefClass}, |
5 | search::SearchScope, | 5 | search::SearchScope, |
@@ -49,7 +49,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti | |||
49 | 49 | ||
50 | let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; | 50 | let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?; |
51 | let imported_defs = find_imported_defs(ctx, star)?; | 51 | let imported_defs = find_imported_defs(ctx, star)?; |
52 | let names_to_import = find_names_to_import(ctx, current_scope, refs_in_target, imported_defs); | 52 | let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs); |
53 | 53 | ||
54 | let target = parent.clone().either(|n| n.syntax().clone(), |n| n.syntax().clone()); | 54 | let target = parent.clone().either(|n| n.syntax().clone(), |n| n.syntax().clone()); |
55 | acc.add( | 55 | acc.add( |
@@ -90,6 +90,18 @@ enum Def { | |||
90 | MacroDef(MacroDef), | 90 | MacroDef(MacroDef), |
91 | } | 91 | } |
92 | 92 | ||
93 | impl Def { | ||
94 | fn is_referenced_in(&self, ctx: &AssistContext) -> bool { | ||
95 | let def = match self { | ||
96 | Def::ModuleDef(def) => Definition::ModuleDef(*def), | ||
97 | Def::MacroDef(def) => Definition::Macro(*def), | ||
98 | }; | ||
99 | |||
100 | let search_scope = SearchScope::single_file(ctx.frange.file_id); | ||
101 | !def.find_usages(&ctx.sema, Some(search_scope)).is_empty() | ||
102 | } | ||
103 | } | ||
104 | |||
93 | #[derive(Debug, Clone)] | 105 | #[derive(Debug, Clone)] |
94 | struct Ref { | 106 | struct Ref { |
95 | // could be alias | 107 | // could be alias |
@@ -105,35 +117,39 @@ impl Ref { | |||
105 | _ => None, | 117 | _ => None, |
106 | } | 118 | } |
107 | } | 119 | } |
108 | |||
109 | fn is_referenced_in(&self, ctx: &AssistContext, scope: &SemanticsScope) -> bool { | ||
110 | let def = match self.def { | ||
111 | Def::ModuleDef(def) => Definition::ModuleDef(def), | ||
112 | Def::MacroDef(def) => Definition::Macro(def), | ||
113 | }; | ||
114 | |||
115 | if let Definition::ModuleDef(ModuleDef::Trait(tr)) = def { | ||
116 | if scope | ||
117 | .traits_in_scope() | ||
118 | .into_iter() | ||
119 | .find(|other_tr_id| tr == other_tr_id.to_owned().into()) | ||
120 | .is_some() | ||
121 | { | ||
122 | return true; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | let search_scope = SearchScope::single_file(ctx.frange.file_id); | ||
127 | !def.find_usages(&ctx.sema, Some(search_scope)).is_empty() | ||
128 | } | ||
129 | } | 120 | } |
130 | 121 | ||
131 | #[derive(Debug, Clone)] | 122 | #[derive(Debug, Clone)] |
132 | struct Refs(Vec<Ref>); | 123 | struct Refs(Vec<Ref>); |
133 | 124 | ||
134 | impl Refs { | 125 | impl Refs { |
135 | fn used_refs(&self, ctx: &AssistContext, scope: &SemanticsScope) -> Refs { | 126 | fn used_refs(&self, ctx: &AssistContext) -> Refs { |
136 | Refs(self.0.clone().into_iter().filter(|r| r.is_referenced_in(ctx, scope)).collect()) | 127 | Refs( |
128 | self.0 | ||
129 | .clone() | ||
130 | .into_iter() | ||
131 | .filter(|r| { | ||
132 | if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def { | ||
133 | if tr | ||
134 | .items(ctx.db()) | ||
135 | .into_iter() | ||
136 | .find(|ai| { | ||
137 | if let AssocItem::Function(f) = *ai { | ||
138 | Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx) | ||
139 | } else { | ||
140 | false | ||
141 | } | ||
142 | }) | ||
143 | .is_some() | ||
144 | { | ||
145 | return true; | ||
146 | } | ||
147 | } | ||
148 | |||
149 | r.def.is_referenced_in(ctx) | ||
150 | }) | ||
151 | .collect(), | ||
152 | ) | ||
137 | } | 153 | } |
138 | 154 | ||
139 | fn filter_out_by_defs(&self, defs: Vec<Def>) -> Refs { | 155 | fn filter_out_by_defs(&self, defs: Vec<Def>) -> Refs { |
@@ -191,11 +207,10 @@ fn find_imported_defs(ctx: &AssistContext, star: SyntaxToken) -> Option<Vec<Def> | |||
191 | 207 | ||
192 | fn find_names_to_import( | 208 | fn find_names_to_import( |
193 | ctx: &AssistContext, | 209 | ctx: &AssistContext, |
194 | current_scope: SemanticsScope, | ||
195 | refs_in_target: Refs, | 210 | refs_in_target: Refs, |
196 | imported_defs: Vec<Def>, | 211 | imported_defs: Vec<Def>, |
197 | ) -> Vec<Name> { | 212 | ) -> Vec<Name> { |
198 | let used_refs = refs_in_target.used_refs(ctx, ¤t_scope).filter_out_by_defs(imported_defs); | 213 | let used_refs = refs_in_target.used_refs(ctx).filter_out_by_defs(imported_defs); |
199 | used_refs.0.iter().map(|r| r.visible_name.clone()).collect() | 214 | used_refs.0.iter().map(|r| r.visible_name.clone()).collect() |
200 | } | 215 | } |
201 | 216 | ||
@@ -767,7 +782,37 @@ fn main() { | |||
767 | ().method(); | 782 | ().method(); |
768 | } | 783 | } |
769 | ", | 784 | ", |
770 | ) | 785 | ); |
786 | |||
787 | check_assist( | ||
788 | expand_glob_import, | ||
789 | r" | ||
790 | //- /lib.rs crate:foo | ||
791 | pub trait Tr { | ||
792 | fn method(&self) {} | ||
793 | } | ||
794 | impl Tr for () {} | ||
795 | |||
796 | pub trait Tr2 { | ||
797 | fn method2(&self) {} | ||
798 | } | ||
799 | impl Tr2 for () {} | ||
800 | |||
801 | //- /main.rs crate:main deps:foo | ||
802 | use foo::*<|>; | ||
803 | |||
804 | fn main() { | ||
805 | ().method(); | ||
806 | } | ||
807 | ", | ||
808 | r" | ||
809 | use foo::Tr; | ||
810 | |||
811 | fn main() { | ||
812 | ().method(); | ||
813 | } | ||
814 | ", | ||
815 | ); | ||
771 | } | 816 | } |
772 | 817 | ||
773 | #[test] | 818 | #[test] |