Skip to content

Commit 3705f71

Browse files
authored
Merge pull request #20710 from A4-Tacks/unused-var-shorthand
Fix unused_variables fixes shorthand record field
2 parents 6d5bfae + a41ca50 commit 3705f71

File tree

1 file changed

+57
-11
lines changed

1 file changed

+57
-11
lines changed

crates/ide-diagnostics/src/handlers/unused_variables.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use ide_db::{
66
label::Label,
77
source_change::SourceChange,
88
};
9-
use syntax::{Edition, TextRange};
9+
use syntax::{AstNode, Edition, TextRange};
1010

1111
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
1212

@@ -24,15 +24,21 @@ pub(crate) fn unused_variables(
2424
}
2525
let diagnostic_range = ctx.sema.diagnostics_display_range(ast);
2626
// The range for the Actual Name. We don't want to replace the entire declaration. Using the diagnostic range causes issues within in Array Destructuring.
27-
let name_range = d
28-
.local
29-
.primary_source(ctx.sema.db)
27+
let primary_source = d.local.primary_source(ctx.sema.db);
28+
let name_range = primary_source
3029
.name()
3130
.map(|v| v.syntax().original_file_range_rooted(ctx.sema.db))
3231
.filter(|it| {
3332
Some(it.file_id) == ast.file_id.file_id()
3433
&& diagnostic_range.range.contains_range(it.range)
3534
});
35+
let is_shorthand_field = primary_source
36+
.source
37+
.value
38+
.left()
39+
.and_then(|name| name.syntax().parent())
40+
.and_then(syntax::ast::RecordPatField::cast)
41+
.is_some_and(|field| field.colon_token().is_none());
3642
let var_name = d.local.name(ctx.sema.db);
3743
Some(
3844
Diagnostic::new_with_syntax_node_ptr(
@@ -48,6 +54,7 @@ pub(crate) fn unused_variables(
4854
it.range,
4955
diagnostic_range,
5056
ast.file_id.is_macro(),
57+
is_shorthand_field,
5158
ctx.edition,
5259
)
5360
})),
@@ -60,24 +67,23 @@ fn fixes(
6067
name_range: TextRange,
6168
diagnostic_range: FileRange,
6269
is_in_marco: bool,
70+
is_shorthand_field: bool,
6371
edition: Edition,
6472
) -> Option<Vec<Assist>> {
6573
if is_in_marco {
6674
return None;
6775
}
76+
let name = var_name.display(db, edition);
77+
let new_name = if is_shorthand_field { format!("{name}: _{name}") } else { format!("_{name}") };
6878

6979
Some(vec![Assist {
7080
id: AssistId::quick_fix("unscore_unused_variable_name"),
71-
label: Label::new(format!(
72-
"Rename unused {} to _{}",
73-
var_name.display(db, edition),
74-
var_name.display(db, edition)
75-
)),
81+
label: Label::new(format!("Rename unused {name} to {new_name}")),
7682
group: None,
7783
target: diagnostic_range.range,
7884
source_change: Some(SourceChange::from_text_edit(
7985
diagnostic_range.file_id,
80-
TextEdit::replace(name_range, format!("_{}", var_name.display(db, edition))),
86+
TextEdit::replace(name_range, new_name),
8187
)),
8288
command: None,
8389
}])
@@ -220,7 +226,7 @@ struct Foo { f1: i32, f2: i64 }
220226
fn main() {
221227
let f = Foo { f1: 0, f2: 0 };
222228
match f {
223-
Foo { _f1, f2 } => {
229+
Foo { f1: _f1, f2 } => {
224230
_ = f2;
225231
}
226232
}
@@ -263,6 +269,46 @@ fn main() {
263269
);
264270
}
265271

272+
#[test]
273+
fn unused_variable_in_record_field() {
274+
check_fix(
275+
r#"
276+
struct S { field : u32 }
277+
fn main() {
278+
let s = S { field : 2 };
279+
let S { field: $0x } = s
280+
}
281+
"#,
282+
r#"
283+
struct S { field : u32 }
284+
fn main() {
285+
let s = S { field : 2 };
286+
let S { field: _x } = s
287+
}
288+
"#,
289+
);
290+
}
291+
292+
#[test]
293+
fn unused_variable_in_shorthand_record_field() {
294+
check_fix(
295+
r#"
296+
struct S { field : u32 }
297+
fn main() {
298+
let s = S { field : 2 };
299+
let S { $0field } = s
300+
}
301+
"#,
302+
r#"
303+
struct S { field : u32 }
304+
fn main() {
305+
let s = S { field : 2 };
306+
let S { field: _field } = s
307+
}
308+
"#,
309+
);
310+
}
311+
266312
// regression test as we used to panic in this scenario
267313
#[test]
268314
fn unknown_struct_pattern_param_type() {

0 commit comments

Comments
 (0)