@@ -3,10 +3,11 @@ use hir::{AssocItem, Enum, HasVisibility, Module, ModuleDef, Name, PathResolutio
3
3
use ide_db:: {
4
4
defs:: { Definition , NameRefClass } ,
5
5
search:: SearchScope ,
6
+ source_change:: SourceChangeBuilder ,
6
7
} ;
7
8
use stdx:: never;
8
9
use syntax:: {
9
- ast:: { self , make} ,
10
+ ast:: { self , make, Use , UseTree } ,
10
11
ted, AstNode , Direction , SyntaxNode , SyntaxToken , T ,
11
12
} ;
12
13
@@ -43,6 +44,7 @@ use crate::{
43
44
pub ( crate ) fn expand_glob_import ( acc : & mut Assists , ctx : & AssistContext < ' _ > ) -> Option < ( ) > {
44
45
let star = ctx. find_token_syntax_at_offset ( T ! [ * ] ) ?;
45
46
let use_tree = star. parent ( ) . and_then ( ast:: UseTree :: cast) ?;
47
+ let use_item = star. parent_ancestors ( ) . find_map ( ast:: Use :: cast) ?;
46
48
let ( parent, mod_path) = find_parent_and_path ( & star) ?;
47
49
let target_module = match ctx. sema . resolve_path ( & mod_path) ? {
48
50
PathResolution :: Def ( ModuleDef :: Module ( it) ) => Expandable :: Module ( it) ,
@@ -53,46 +55,61 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) ->
53
55
let current_scope = ctx. sema . scope ( & star. parent ( ) ?) ?;
54
56
let current_module = current_scope. module ( ) ;
55
57
56
- let refs_in_target = find_refs_in_mod ( ctx, target_module, current_module) ?;
57
- let imported_defs = find_imported_defs ( ctx, star) ?;
58
+ if !is_visible_from ( ctx, & target_module, current_module) {
59
+ return None ;
60
+ }
58
61
59
62
let target = parent. either ( |n| n. syntax ( ) . clone ( ) , |n| n. syntax ( ) . clone ( ) ) ;
60
63
acc. add (
61
64
AssistId ( "expand_glob_import" , AssistKind :: RefactorRewrite ) ,
62
65
"Expand glob import" ,
63
66
target. text_range ( ) ,
64
67
|builder| {
65
- let use_tree = builder. make_mut ( use_tree) ;
66
-
67
- let names_to_import = find_names_to_import ( ctx, refs_in_target, imported_defs) ;
68
- let expanded = make:: use_tree_list ( names_to_import. iter ( ) . map ( |n| {
69
- let path = make:: ext:: ident_path (
70
- & n. display ( ctx. db ( ) , current_module. krate ( ) . edition ( ctx. db ( ) ) ) . to_string ( ) ,
71
- ) ;
72
- make:: use_tree ( path, None , None , false )
73
- } ) )
74
- . clone_for_update ( ) ;
75
-
76
- match use_tree. star_token ( ) {
77
- Some ( star) => {
78
- let needs_braces = use_tree. path ( ) . is_some ( ) && names_to_import. len ( ) != 1 ;
79
- if needs_braces {
80
- ted:: replace ( star, expanded. syntax ( ) )
81
- } else {
82
- let without_braces = expanded
83
- . syntax ( )
84
- . children_with_tokens ( )
85
- . filter ( |child| !matches ! ( child. kind( ) , T ![ '{' ] | T ![ '}' ] ) )
86
- . collect ( ) ;
87
- ted:: replace_with_many ( star, without_braces)
88
- }
89
- }
90
- None => never ! ( ) ,
91
- }
68
+ build_expanded_import ( ctx, builder, use_tree, use_item, target_module, current_module)
92
69
} ,
93
70
)
94
71
}
95
72
73
+ fn build_expanded_import (
74
+ ctx : & AssistContext < ' _ > ,
75
+ builder : & mut SourceChangeBuilder ,
76
+ use_tree : UseTree ,
77
+ use_item : Use ,
78
+ target_module : Expandable ,
79
+ current_module : Module ,
80
+ ) {
81
+ let refs_in_target = find_refs_in_mod ( ctx, target_module, current_module) ;
82
+ let imported_defs = find_imported_defs ( ctx, use_item) ;
83
+
84
+ let use_tree = builder. make_mut ( use_tree) ;
85
+
86
+ let names_to_import = find_names_to_import ( ctx, refs_in_target, imported_defs) ;
87
+ let expanded = make:: use_tree_list ( names_to_import. iter ( ) . map ( |n| {
88
+ let path = make:: ext:: ident_path (
89
+ & n. display ( ctx. db ( ) , current_module. krate ( ) . edition ( ctx. db ( ) ) ) . to_string ( ) ,
90
+ ) ;
91
+ make:: use_tree ( path, None , None , false )
92
+ } ) )
93
+ . clone_for_update ( ) ;
94
+
95
+ match use_tree. star_token ( ) {
96
+ Some ( star) => {
97
+ let needs_braces = use_tree. path ( ) . is_some ( ) && names_to_import. len ( ) != 1 ;
98
+ if needs_braces {
99
+ ted:: replace ( star, expanded. syntax ( ) )
100
+ } else {
101
+ let without_braces = expanded
102
+ . syntax ( )
103
+ . children_with_tokens ( )
104
+ . filter ( |child| !matches ! ( child. kind( ) , T ![ '{' ] | T ![ '}' ] ) )
105
+ . collect ( ) ;
106
+ ted:: replace_with_many ( star, without_braces)
107
+ }
108
+ }
109
+ None => never ! ( ) ,
110
+ }
111
+ }
112
+
96
113
enum Expandable {
97
114
Module ( Module ) ,
98
115
Enum ( Enum ) ,
@@ -176,36 +193,24 @@ impl Refs {
176
193
}
177
194
}
178
195
179
- fn find_refs_in_mod (
180
- ctx : & AssistContext < ' _ > ,
181
- expandable : Expandable ,
182
- visible_from : Module ,
183
- ) -> Option < Refs > {
184
- if !is_expandable_visible_from ( ctx, & expandable, visible_from) {
185
- return None ;
186
- }
187
-
196
+ fn find_refs_in_mod ( ctx : & AssistContext < ' _ > , expandable : Expandable , visible_from : Module ) -> Refs {
188
197
match expandable {
189
198
Expandable :: Module ( module) => {
190
199
let module_scope = module. scope ( ctx. db ( ) , Some ( visible_from) ) ;
191
200
let refs =
192
201
module_scope. into_iter ( ) . filter_map ( |( n, d) | Ref :: from_scope_def ( n, d) ) . collect ( ) ;
193
- Some ( Refs ( refs) )
202
+ Refs ( refs)
194
203
}
195
- Expandable :: Enum ( enm) => Some ( Refs (
204
+ Expandable :: Enum ( enm) => Refs (
196
205
enm. variants ( ctx. db ( ) )
197
206
. into_iter ( )
198
207
. map ( |v| Ref { visible_name : v. name ( ctx. db ( ) ) , def : Definition :: Variant ( v) } )
199
208
. collect ( ) ,
200
- ) ) ,
209
+ ) ,
201
210
}
202
211
}
203
212
204
- fn is_expandable_visible_from (
205
- ctx : & AssistContext < ' _ > ,
206
- expandable : & Expandable ,
207
- from : Module ,
208
- ) -> bool {
213
+ fn is_visible_from ( ctx : & AssistContext < ' _ > , expandable : & Expandable , from : Module ) -> bool {
209
214
fn is_mod_visible_from ( ctx : & AssistContext < ' _ > , module : Module , from : Module ) -> bool {
210
215
match module. parent ( ctx. db ( ) ) {
211
216
Some ( parent) => {
@@ -246,41 +251,29 @@ fn is_expandable_visible_from(
246
251
// use foo::*$0;
247
252
// use baz::Baz;
248
253
// ↑ ---------------
249
- fn find_imported_defs ( ctx : & AssistContext < ' _ > , star : SyntaxToken ) -> Option < Vec < Definition > > {
250
- let parent_use_item_syntax = star. parent_ancestors ( ) . find_map ( |n| {
251
- if ast:: Use :: can_cast ( n. kind ( ) ) {
252
- Some ( n)
253
- } else {
254
- None
255
- }
256
- } ) ?;
257
-
258
- Some (
259
- [ Direction :: Prev , Direction :: Next ]
260
- . into_iter ( )
261
- . flat_map ( |dir| {
262
- parent_use_item_syntax
263
- . siblings ( dir. to_owned ( ) )
264
- . filter ( |n| ast:: Use :: can_cast ( n. kind ( ) ) )
265
- } )
266
- . flat_map ( |n| n. descendants ( ) . filter_map ( ast:: NameRef :: cast) )
267
- . filter_map ( |r| match NameRefClass :: classify ( & ctx. sema , & r) ? {
268
- NameRefClass :: Definition (
269
- def @ ( Definition :: Macro ( _)
270
- | Definition :: Module ( _)
271
- | Definition :: Function ( _)
272
- | Definition :: Adt ( _)
273
- | Definition :: Variant ( _)
274
- | Definition :: Const ( _)
275
- | Definition :: Static ( _)
276
- | Definition :: Trait ( _)
277
- | Definition :: TypeAlias ( _) ) ,
278
- _,
279
- ) => Some ( def) ,
280
- _ => None ,
281
- } )
282
- . collect ( ) ,
283
- )
254
+ fn find_imported_defs ( ctx : & AssistContext < ' _ > , use_item : Use ) -> Vec < Definition > {
255
+ [ Direction :: Prev , Direction :: Next ]
256
+ . into_iter ( )
257
+ . flat_map ( |dir| {
258
+ use_item. syntax ( ) . siblings ( dir. to_owned ( ) ) . filter ( |n| ast:: Use :: can_cast ( n. kind ( ) ) )
259
+ } )
260
+ . flat_map ( |n| n. descendants ( ) . filter_map ( ast:: NameRef :: cast) )
261
+ . filter_map ( |r| match NameRefClass :: classify ( & ctx. sema , & r) ? {
262
+ NameRefClass :: Definition (
263
+ def @ ( Definition :: Macro ( _)
264
+ | Definition :: Module ( _)
265
+ | Definition :: Function ( _)
266
+ | Definition :: Adt ( _)
267
+ | Definition :: Variant ( _)
268
+ | Definition :: Const ( _)
269
+ | Definition :: Static ( _)
270
+ | Definition :: Trait ( _)
271
+ | Definition :: TypeAlias ( _) ) ,
272
+ _,
273
+ ) => Some ( def) ,
274
+ _ => None ,
275
+ } )
276
+ . collect ( )
284
277
}
285
278
286
279
fn find_names_to_import (
0 commit comments