11use hir:: AsAssocItem ;
2- use syntax:: {
3- TextRange ,
4- ast:: { self , AstNode , HasArgList , prec:: ExprPrecedence } ,
5- } ;
2+ use syntax:: ast:: { self , AstNode , HasArgList , prec:: ExprPrecedence , syntax_factory:: SyntaxFactory } ;
63
74use crate :: { AssistContext , AssistId , Assists } ;
85
@@ -36,10 +33,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
3633 }
3734
3835 let args = call. arg_list ( ) ?;
39- let l_paren = args. l_paren_token ( ) ?;
40- let mut args_iter = args. args ( ) ;
41- let first_arg = args_iter. next ( ) ?;
42- let second_arg = args_iter. next ( ) ;
36+ let first_arg = args. args ( ) . next ( ) ?;
4337
4438 let qualifier = path. qualifier ( ) ?;
4539 let method_name = path. segment ( ) ?. name_ref ( ) ?;
@@ -51,51 +45,42 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
5145 return None ;
5246 }
5347
54- // `core::ops::Add::add(` -> ``
55- let delete_path =
56- TextRange :: new ( path. syntax ( ) . text_range ( ) . start ( ) , l_paren. text_range ( ) . end ( ) ) ;
57-
58- // Parens around `expr` if needed
59- let parens = first_arg. precedence ( ) . needs_parentheses_in ( ExprPrecedence :: Postfix ) . then ( || {
60- let range = first_arg. syntax ( ) . text_range ( ) ;
61- ( range. start ( ) , range. end ( ) )
62- } ) ;
63-
64- // `, ` -> `.add(`
65- let replace_comma = TextRange :: new (
66- first_arg. syntax ( ) . text_range ( ) . end ( ) ,
67- second_arg
68- . map ( |a| a. syntax ( ) . text_range ( ) . start ( ) )
69- . unwrap_or_else ( || first_arg. syntax ( ) . text_range ( ) . end ( ) ) ,
70- ) ;
71-
7248 acc. add (
7349 AssistId :: refactor_rewrite ( "unqualify_method_call" ) ,
7450 "Unqualify method call" ,
7551 call. syntax ( ) . text_range ( ) ,
76- |edit| {
77- edit. delete ( delete_path) ;
78- if let Some ( ( open, close) ) = parens {
79- edit. insert ( open, "(" ) ;
80- edit. insert ( close, ")" ) ;
81- }
82- edit. replace ( replace_comma, format ! ( ".{method_name}(" ) ) ;
52+ |builder| {
53+ let make = SyntaxFactory :: with_mappings ( ) ;
54+ let mut editor = builder. make_editor ( call. syntax ( ) ) ;
55+
56+ let new_arg_list = make. arg_list ( args. args ( ) . skip ( 1 ) ) ;
57+ let receiver = if first_arg. precedence ( ) . needs_parentheses_in ( ExprPrecedence :: Postfix ) {
58+ ast:: Expr :: from ( make. expr_paren ( first_arg. clone ( ) ) )
59+ } else {
60+ first_arg. clone ( )
61+ } ;
62+ let method_call = make. expr_method_call ( receiver, method_name, new_arg_list) ;
63+
64+ editor. replace ( call. syntax ( ) , method_call. syntax ( ) ) ;
8365
8466 if let Some ( fun) = fun. as_assoc_item ( ctx. db ( ) )
8567 && let Some ( trait_) = fun. container_or_implemented_trait ( ctx. db ( ) )
8668 && !scope. can_use_trait_methods ( trait_)
8769 {
88- // Only add an import for trait methods that are not already imported.
89- add_import ( qualifier, ctx, edit) ;
70+ add_import ( qualifier, ctx, & make, & mut editor) ;
9071 }
72+
73+ editor. add_mappings ( make. finish_with_mappings ( ) ) ;
74+ builder. add_file_edits ( ctx. vfs_file_id ( ) , editor) ;
9175 } ,
9276 )
9377}
9478
9579fn add_import (
9680 qualifier : ast:: Path ,
9781 ctx : & AssistContext < ' _ > ,
98- edit : & mut ide_db:: source_change:: SourceChangeBuilder ,
82+ make : & SyntaxFactory ,
83+ editor : & mut syntax:: syntax_editor:: SyntaxEditor ,
9984) {
10085 if let Some ( path_segment) = qualifier. segment ( ) {
10186 // for `<i32 as std::ops::Add>`
@@ -122,8 +107,13 @@ fn add_import(
122107 ) ;
123108
124109 if let Some ( scope) = scope {
125- let scope = edit. make_import_scope_mut ( scope) ;
126- ide_db:: imports:: insert_use:: insert_use ( & scope, import, & ctx. config . insert_use ) ;
110+ ide_db:: imports:: insert_use:: insert_use_with_editor (
111+ & scope,
112+ import,
113+ & ctx. config . insert_use ,
114+ editor,
115+ make,
116+ ) ;
127117 }
128118 }
129119}
0 commit comments