@@ -3,7 +3,10 @@ use ide_db::helpers::{
33 insert_use:: { insert_use, ImportScope } ,
44 mod_path_to_ast,
55} ;
6- use syntax:: { ast, match_ast, ted, AstNode , SyntaxNode } ;
6+ use syntax:: {
7+ ast:: { self , make} ,
8+ match_ast, ted, AstNode , SyntaxNode ,
9+ } ;
710
811use crate :: { AssistContext , AssistId , AssistKind , Assists } ;
912
@@ -38,20 +41,26 @@ pub(crate) fn replace_qualified_name_with_use(
3841 return None ;
3942 }
4043
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,
4554 _ => return None ,
4655 } ;
4756
48- let target = path. syntax ( ) . text_range ( ) ;
4957 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 (
5159 ctx. sema . db ,
52- def ,
60+ module ,
5361 ctx. config . insert_use . prefix_kind ,
5462 ) ?;
63+ let target = path. syntax ( ) . text_range ( ) ;
5564 acc. add (
5665 AssistId ( "replace_qualified_name_with_use" , AssistKind :: RefactorRewrite ) ,
5766 "Replace qualified path with use" ,
@@ -64,7 +73,11 @@ pub(crate) fn replace_qualified_name_with_use(
6473 ImportScope :: Module ( it) => ImportScope :: Module ( builder. make_mut ( it) ) ,
6574 ImportScope :: Block ( it) => ImportScope :: Block ( builder. make_mut ( it) ) ,
6675 } ;
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+ } ;
6881 shorten_paths ( scope. as_syntax_node ( ) , & path. clone_for_update ( ) ) ;
6982 insert_use ( & scope, path, & ctx. config . insert_use ) ;
7083 } ,
@@ -300,6 +313,41 @@ impl Foo {
300313fn main() {
301314 Foo::foo$0();
302315}
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+ }
303351" ,
304352 ) ;
305353 }
0 commit comments