@@ -37,6 +37,8 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
3737 _ => return None ,
3838 } ;
3939 let func = param. syntax ( ) . ancestors ( ) . find_map ( ast:: Fn :: cast) ?;
40+ let is_self_present =
41+ param. syntax ( ) . parent ( ) ?. children ( ) . find_map ( ast:: SelfParam :: cast) . is_some ( ) ;
4042
4143 // check if fn is in impl Trait for ..
4244 if func
@@ -50,7 +52,16 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
5052 return None ;
5153 }
5254
53- let param_position = func. param_list ( ) ?. params ( ) . position ( |it| it == param) ?;
55+ let mut param_position = func. param_list ( ) ?. params ( ) . position ( |it| it == param) ?;
56+ // param_list() does not take self param into consideration, hence this additional check is
57+ // added. There are two cases to handle in this scenario, where functions are
58+ // associative(functions not associative and not containting contain self, are not allowed), in
59+ // this case param position is rightly set. If a method call is present which has self param,
60+ // that needs to be handled and is added below in process_usage function to reduce this increment and
61+ // not consider self param.
62+ if is_self_present {
63+ param_position += 1 ;
64+ }
5465 let fn_def = {
5566 let func = ctx. sema . to_def ( & func) ?;
5667 Definition :: ModuleDef ( func. into ( ) )
@@ -71,7 +82,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
7182 |builder| {
7283 builder. delete ( range_to_remove ( param. syntax ( ) ) ) ;
7384 for ( file_id, references) in fn_def. usages ( & ctx. sema ) . all ( ) {
74- process_usages ( ctx, builder, file_id, references, param_position) ;
85+ process_usages ( ctx, builder, file_id, references, param_position, is_self_present ) ;
7586 }
7687 } ,
7788 )
@@ -83,11 +94,13 @@ fn process_usages(
8394 file_id : FileId ,
8495 references : Vec < FileReference > ,
8596 arg_to_remove : usize ,
97+ is_self_present : bool ,
8698) {
8799 let source_file = ctx. sema . parse ( file_id) ;
88100 builder. edit_file ( file_id) ;
89101 for usage in references {
90- if let Some ( text_range) = process_usage ( & source_file, usage, arg_to_remove) {
102+ if let Some ( text_range) = process_usage ( & source_file, usage, arg_to_remove, is_self_present)
103+ {
91104 builder. delete ( text_range) ;
92105 }
93106 }
@@ -96,15 +109,37 @@ fn process_usages(
96109fn process_usage (
97110 source_file : & SourceFile ,
98111 FileReference { range, .. } : FileReference ,
99- arg_to_remove : usize ,
112+ mut arg_to_remove : usize ,
113+ is_self_present : bool ,
100114) -> Option < TextRange > {
101- let call_expr: ast:: CallExpr = find_node_at_range ( source_file. syntax ( ) , range) ?;
102- let call_expr_range = call_expr. expr ( ) ?. syntax ( ) . text_range ( ) ;
103- if !call_expr_range. contains_range ( range) {
104- return None ;
115+ let call_expr_opt: Option < ast:: CallExpr > = find_node_at_range ( source_file. syntax ( ) , range) ;
116+ if let Some ( call_expr) = call_expr_opt {
117+ let call_expr_range = call_expr. expr ( ) ?. syntax ( ) . text_range ( ) ;
118+ if !call_expr_range. contains_range ( range) {
119+ return None ;
120+ }
121+
122+ let arg = call_expr. arg_list ( ) ?. args ( ) . nth ( arg_to_remove) ?;
123+ return Some ( range_to_remove ( arg. syntax ( ) ) ) ;
105124 }
106- let arg = call_expr. arg_list ( ) ?. args ( ) . nth ( arg_to_remove) ?;
107- Some ( range_to_remove ( arg. syntax ( ) ) )
125+
126+ let method_call_expr_opt: Option < ast:: MethodCallExpr > =
127+ find_node_at_range ( source_file. syntax ( ) , range) ;
128+ if let Some ( method_call_expr) = method_call_expr_opt {
129+ let method_call_expr_range = method_call_expr. name_ref ( ) ?. syntax ( ) . text_range ( ) ;
130+ if !method_call_expr_range. contains_range ( range) {
131+ return None ;
132+ }
133+
134+ if is_self_present {
135+ arg_to_remove -= 1 ;
136+ }
137+
138+ let arg = method_call_expr. arg_list ( ) ?. args ( ) . nth ( arg_to_remove) ?;
139+ return Some ( range_to_remove ( arg. syntax ( ) ) ) ;
140+ }
141+
142+ return None ;
108143}
109144
110145fn range_to_remove ( node : & SyntaxNode ) -> TextRange {
@@ -315,10 +350,7 @@ fn bar() {
315350 }
316351
317352 #[ test]
318- fn remove_method_param ( ) {
319- // FIXME: This is completely wrong:
320- // * method call expressions are not handled
321- // * assoc function syntax removes the wrong argument.
353+ fn test_remove_method_param ( ) {
322354 check_assist (
323355 remove_unused_param,
324356 r#"
@@ -327,18 +359,18 @@ impl S { fn f(&self, $0_unused: i32) {} }
327359fn main() {
328360 S.f(92);
329361 S.f();
330- S.f(92 , 92);
362+ S.f(93 , 92);
331363 S::f(&S, 92);
332364}
333365"# ,
334366 r#"
335367struct S;
336368impl S { fn f(&self) {} }
337369fn main() {
338- S.f(92);
339370 S.f();
340- S.f(92, 92);
341- S::f(92);
371+ S.f();
372+ S.f(92);
373+ S::f(&S);
342374}
343375"# ,
344376 )
0 commit comments