Skip to content

Commit ae8a02c

Browse files
committed
Add support for chaning ref argument definition to mutable
1 parent 05dd765 commit ae8a02c

File tree

3 files changed

+113
-31
lines changed

3 files changed

+113
-31
lines changed

src/ide/code_actions/make_variable_mutable.rs

Lines changed: 47 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,52 @@ pub fn make_variable_mutable<'db>(
2121

2222
let identifier =
2323
token.ancestors_with_self(db).find_map(|node| TerminalIdentifier::cast(db, node))?;
24-
let definition_location = SymbolSearch::find_definition(db, &identifier)?
25-
.def
26-
.definition_originating_location(db)?;
27-
let definition = db.find_syntax_node_at_offset(
28-
definition_location.file_id,
29-
definition_location.span.start,
30-
)?;
31-
32-
let span_to_edit = definition
33-
.span_without_trivia(db)
34-
.position_in_file(db, definition.stable_ptr(db).file_id(db))?;
35-
36-
let edits = vec![TextEdit {
37-
range: span_to_edit.to_lsp(),
38-
new_text: format!("mut {}", definition.get_text_without_trivia(db).to_string(db)),
39-
}];
40-
41-
Some(CodeAction {
42-
title: "Change it to be mutable".to_string(),
43-
kind: Some(CodeActionKind::QUICKFIX),
44-
edit: Some(WorkspaceEdit {
45-
changes: Some(HashMap::from([(uri.clone(), edits)])),
46-
document_changes: None,
47-
change_annotations: None,
48-
}),
49-
..Default::default()
50-
})
24+
get_mutable_variable_action(db, identifier, uri.clone())
25+
})
26+
}
27+
28+
pub fn make_ref_variable_mutable<'db>(
29+
db: &'db AnalysisDatabase,
30+
node: SyntaxNode<'db>,
31+
uri: Url,
32+
) -> Option<CodeAction> {
33+
db.get_node_resultants(node)?.iter().find_map(|resultant_node| {
34+
let identifier = resultant_node
35+
.ancestors_with_self(db)
36+
.find_map(|node| TerminalIdentifier::cast(db, node))?;
37+
get_mutable_variable_action(db, identifier, uri.clone())
38+
})
39+
}
40+
41+
fn get_mutable_variable_action<'db>(
42+
db: &'db AnalysisDatabase,
43+
identifier: TerminalIdentifier<'db>,
44+
uri: Url,
45+
) -> Option<CodeAction> {
46+
let definition_location =
47+
SymbolSearch::find_definition(db, &identifier)?.def.definition_originating_location(db)?;
48+
let definition =
49+
db.find_syntax_node_at_offset(definition_location.file_id, definition_location.span.start)?;
50+
51+
let span_to_edit =
52+
definition.span_without_trivia(db).position_in_file(db, definition.file_id(db))?;
53+
54+
let edits = vec![TextEdit {
55+
range: span_to_edit.to_lsp(),
56+
new_text: format!("mut {}", definition.get_text_without_trivia(db).to_string(db)),
57+
}];
58+
59+
Some(CodeAction {
60+
title: format!(
61+
"Change \"{}\" to be mutable",
62+
definition.get_text_without_trivia(db).to_string(db)
63+
),
64+
kind: Some(CodeActionKind::QUICKFIX),
65+
edit: Some(WorkspaceEdit {
66+
changes: Some(HashMap::from([(uri.clone(), edits)])),
67+
document_changes: None,
68+
change_annotations: None,
69+
}),
70+
..Default::default()
5171
})
5272
}

src/ide/code_actions/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ fn get_code_actions_for_diagnostics(
124124
Some("E2083") => {
125125
make_variable_mutable::make_variable_mutable(db, ctx.node, uri.clone()).to_vec()
126126
}
127+
Some("E2080") => {
128+
make_variable_mutable::make_ref_variable_mutable(db, ctx.node, uri.clone()).to_vec()
129+
}
127130
Some(code) => {
128131
debug!("no code actions for diagnostic code: {code}");
129132
vec![]

tests/e2e/code_actions/make_variable_mutable.rs

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn change_to_mutable_let_definition() {
99
a = 25<caret>;
1010
}
1111
", @r#"
12-
Title: Change it to be mutable
12+
Title: Change "a" to be mutable
1313
Add new text: "mut a"
1414
At: Range { start: Position { line: 1, character: 8 }, end: Position { line: 1, character: 9 } }
1515
"#);
@@ -22,7 +22,7 @@ fn change_to_mutable_param_definition() {
2222
a = 25<caret>;
2323
}
2424
", @r#"
25-
Title: Change it to be mutable
25+
Title: Change "a" to be mutable
2626
Add new text: "mut a"
2727
At: Range { start: Position { line: 0, character: 7 }, end: Position { line: 0, character: 8 } }
2828
"#);
@@ -37,7 +37,7 @@ fn change_to_mutable_let_definition_with_macros() {
3737
a = 25<caret>;
3838
}
3939
", @r#"
40-
Title: Change it to be mutable
40+
Title: Change "a" to be mutable
4141
Add new text: "mut a"
4242
At: Range { start: Position { line: 2, character: 8 }, end: Position { line: 2, character: 9 } }
4343
"#);
@@ -51,8 +51,67 @@ fn change_to_mutable_param_definition_with_macros() {
5151
a = 25<caret>;
5252
}
5353
", @r#"
54-
Title: Change it to be mutable
54+
Title: Change "a" to be mutable
5555
Add new text: "mut a"
5656
At: Range { start: Position { line: 1, character: 7 }, end: Position { line: 1, character: 8 } }
5757
"#);
5858
}
59+
60+
#[test]
61+
fn change_ref_argument_to_mutable() {
62+
test_transform!(quick_fix, "
63+
#[derive(Copy, Drop)]
64+
struct X {}
65+
66+
trait Abc {
67+
fn abc(self: X, ref a: felt252) {}
68+
}
69+
70+
71+
impl AbcImpl of Abc {
72+
fn abc(self: X, ref a: felt252) {
73+
a = 5;
74+
}
75+
}
76+
77+
fn main() {
78+
let x = X {};
79+
let a = 15;
80+
x.abc(ref a<caret>);
81+
}
82+
", @r#"
83+
Title: Change "a" to be mutable
84+
Add new text: "mut a"
85+
At: Range { start: Position { line: 16, character: 8 }, end: Position { line: 16, character: 9 } }
86+
"#);
87+
}
88+
89+
#[test]
90+
fn change_ref_argument_to_mutable_with_macros() {
91+
test_transform!(quick_fix_with_macros, "
92+
#[derive(Copy, Drop)]
93+
struct X {}
94+
95+
trait Abc {
96+
fn abc(self: X, ref a: felt252) {}
97+
}
98+
99+
100+
impl AbcImpl of Abc {
101+
fn abc(self: X, ref a: felt252) {
102+
a = 5;
103+
}
104+
}
105+
106+
#[test]
107+
fn maintest() {
108+
let x = X {};
109+
let a = 15;
110+
x.abc(ref a<caret>);
111+
}
112+
", @r#"
113+
Title: Change "a" to be mutable
114+
Add new text: "mut a"
115+
At: Range { start: Position { line: 17, character: 8 }, end: Position { line: 17, character: 9 } }
116+
"#);
117+
}

0 commit comments

Comments
 (0)