aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src')
-rw-r--r--crates/assists/src/handlers/expand_glob_import.rs101
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 @@
1use either::Either; 1use either::Either;
2use hir::{MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef, SemanticsScope}; 2use hir::{AssocItem, MacroDef, Module, ModuleDef, Name, PathResolution, ScopeDef};
3use ide_db::{ 3use 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
93impl 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)]
94struct Ref { 106struct 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)]
132struct Refs(Vec<Ref>); 123struct Refs(Vec<Ref>);
133 124
134impl Refs { 125impl 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
192fn find_names_to_import( 208fn 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, &current_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
791pub trait Tr {
792 fn method(&self) {}
793}
794impl Tr for () {}
795
796pub trait Tr2 {
797 fn method2(&self) {}
798}
799impl Tr2 for () {}
800
801//- /main.rs crate:main deps:foo
802use foo::*<|>;
803
804fn main() {
805 ().method();
806}
807",
808 r"
809use foo::Tr;
810
811fn main() {
812 ().method();
813}
814",
815 );
771 } 816 }
772 817
773 #[test] 818 #[test]