@@ -37,6 +37,8 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
37
37
_ => return None ,
38
38
} ;
39
39
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 ( ) ;
40
42
41
43
// check if fn is in impl Trait for ..
42
44
if func
@@ -50,7 +52,16 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
50
52
return None ;
51
53
}
52
54
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
+ }
54
65
let fn_def = {
55
66
let func = ctx. sema . to_def ( & func) ?;
56
67
Definition :: ModuleDef ( func. into ( ) )
@@ -71,7 +82,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
71
82
|builder| {
72
83
builder. delete ( range_to_remove ( param. syntax ( ) ) ) ;
73
84
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 ) ;
75
86
}
76
87
} ,
77
88
)
@@ -83,11 +94,13 @@ fn process_usages(
83
94
file_id : FileId ,
84
95
references : Vec < FileReference > ,
85
96
arg_to_remove : usize ,
97
+ is_self_present : bool ,
86
98
) {
87
99
let source_file = ctx. sema . parse ( file_id) ;
88
100
builder. edit_file ( file_id) ;
89
101
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
+ {
91
104
builder. delete ( text_range) ;
92
105
}
93
106
}
@@ -96,15 +109,37 @@ fn process_usages(
96
109
fn process_usage (
97
110
source_file : & SourceFile ,
98
111
FileReference { range, .. } : FileReference ,
99
- arg_to_remove : usize ,
112
+ mut arg_to_remove : usize ,
113
+ is_self_present : bool ,
100
114
) -> 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 ( ) ) ) ;
105
124
}
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 ;
108
143
}
109
144
110
145
fn range_to_remove ( node : & SyntaxNode ) -> TextRange {
@@ -315,10 +350,7 @@ fn bar() {
315
350
}
316
351
317
352
#[ 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 ( ) {
322
354
check_assist (
323
355
remove_unused_param,
324
356
r#"
@@ -327,18 +359,18 @@ impl S { fn f(&self, $0_unused: i32) {} }
327
359
fn main() {
328
360
S.f(92);
329
361
S.f();
330
- S.f(92 , 92);
362
+ S.f(93 , 92);
331
363
S::f(&S, 92);
332
364
}
333
365
"# ,
334
366
r#"
335
367
struct S;
336
368
impl S { fn f(&self) {} }
337
369
fn main() {
338
- S.f(92);
339
370
S.f();
340
- S.f(92, 92);
341
- S::f(92);
371
+ S.f();
372
+ S.f(92);
373
+ S::f(&S);
342
374
}
343
375
"# ,
344
376
)
0 commit comments