@@ -3,7 +3,10 @@ use ide_db::helpers::{
3
3
insert_use:: { insert_use, ImportScope } ,
4
4
mod_path_to_ast,
5
5
} ;
6
- use syntax:: { ast, match_ast, ted, AstNode , SyntaxNode } ;
6
+ use syntax:: {
7
+ ast:: { self , make} ,
8
+ match_ast, ted, AstNode , SyntaxNode ,
9
+ } ;
7
10
8
11
use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
9
12
@@ -38,20 +41,26 @@ pub(crate) fn replace_qualified_name_with_use(
38
41
return None ;
39
42
}
40
43
41
- let res = ctx. sema . resolve_path ( & path) ?;
42
- let def: hir:: ItemInNs = match res {
43
- hir:: PathResolution :: Def ( def) if def. as_assoc_item ( ctx. sema . db ) . is_none ( ) => def. into ( ) ,
44
- hir:: PathResolution :: Macro ( mac) => mac. into ( ) ,
44
+ // only offer replacement for non assoc items
45
+ match ctx. sema . resolve_path ( & path) ? {
46
+ hir:: PathResolution :: Def ( def) if def. as_assoc_item ( ctx. sema . db ) . is_none ( ) => ( ) ,
47
+ hir:: PathResolution :: Macro ( _) => ( ) ,
48
+ _ => return None ,
49
+ }
50
+ // then search for an import for the first path segment of what we want to replace
51
+ // that way it is less likely that we import the item from a different location due re-exports
52
+ let module = match ctx. sema . resolve_path ( & path. first_qualifier_or_self ( ) ) ? {
53
+ hir:: PathResolution :: Def ( module @ hir:: ModuleDef :: Module ( _) ) => module,
45
54
_ => return None ,
46
55
} ;
47
56
48
- let target = path. syntax ( ) . text_range ( ) ;
49
57
let scope = ImportScope :: find_insert_use_container_with_macros ( path. syntax ( ) , & ctx. sema ) ?;
50
- let mod_path = ctx. sema . scope ( path. syntax ( ) ) . module ( ) ?. find_use_path_prefixed (
58
+ let path_to_qualifier = ctx. sema . scope ( path. syntax ( ) ) . module ( ) ?. find_use_path_prefixed (
51
59
ctx. sema . db ,
52
- def ,
60
+ module ,
53
61
ctx. config . insert_use . prefix_kind ,
54
62
) ?;
63
+ let target = path. syntax ( ) . text_range ( ) ;
55
64
acc. add (
56
65
AssistId ( "replace_qualified_name_with_use" , AssistKind :: RefactorRewrite ) ,
57
66
"Replace qualified path with use" ,
@@ -64,7 +73,11 @@ pub(crate) fn replace_qualified_name_with_use(
64
73
ImportScope :: Module ( it) => ImportScope :: Module ( builder. make_mut ( it) ) ,
65
74
ImportScope :: Block ( it) => ImportScope :: Block ( builder. make_mut ( it) ) ,
66
75
} ;
67
- let path = mod_path_to_ast ( & mod_path) ;
76
+ // stick the found import in front of the to be replaced path
77
+ let path = match mod_path_to_ast ( & path_to_qualifier) . qualifier ( ) {
78
+ Some ( qualifier) => make:: path_concat ( qualifier, path) ,
79
+ None => path,
80
+ } ;
68
81
shorten_paths ( scope. as_syntax_node ( ) , & path. clone_for_update ( ) ) ;
69
82
insert_use ( & scope, path, & ctx. config . insert_use ) ;
70
83
} ,
@@ -300,6 +313,41 @@ impl Foo {
300
313
fn main() {
301
314
Foo::foo$0();
302
315
}
316
+ " ,
317
+ ) ;
318
+ }
319
+
320
+ #[ test]
321
+ fn replace_reuses_path_qualifier ( ) {
322
+ check_assist (
323
+ replace_qualified_name_with_use,
324
+ r"
325
+ pub mod foo {
326
+ struct Foo;
327
+ }
328
+
329
+ mod bar {
330
+ pub use super::foo::Foo as Bar;
331
+ }
332
+
333
+ fn main() {
334
+ foo::Foo$0;
335
+ }
336
+ " ,
337
+ r"
338
+ use foo::Foo;
339
+
340
+ pub mod foo {
341
+ struct Foo;
342
+ }
343
+
344
+ mod bar {
345
+ pub use super::foo::Foo as Bar;
346
+ }
347
+
348
+ fn main() {
349
+ Foo;
350
+ }
303
351
" ,
304
352
) ;
305
353
}
0 commit comments