Skip to content

Commit 951c0e9

Browse files
bors[bot]matklad
andauthored
Merge #8948
8948: feat: generate getter assist places the cursor at the generated function r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents e0864c9 + 8696c82 commit 951c0e9

File tree

5 files changed

+141
-252
lines changed

5 files changed

+141
-252
lines changed

crates/ide_assists/src/handlers/generate_getter.rs

Lines changed: 137 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,46 @@ use crate::{
2323
//
2424
// impl Person {
2525
// /// Get a reference to the person's name.
26-
// fn name(&self) -> &String {
26+
// fn $0name(&self) -> &String {
2727
// &self.name
2828
// }
2929
// }
3030
// ```
3131
pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32+
generate_getter_impl(acc, ctx, false)
33+
}
34+
35+
// Assist: generate_getter_mut
36+
//
37+
// Generate a mut getter method.
38+
//
39+
// ```
40+
// struct Person {
41+
// nam$0e: String,
42+
// }
43+
// ```
44+
// ->
45+
// ```
46+
// struct Person {
47+
// name: String,
48+
// }
49+
//
50+
// impl Person {
51+
// /// Get a mutable reference to the person's name.
52+
// fn $0name_mut(&mut self) -> &mut String {
53+
// &mut self.name
54+
// }
55+
// }
56+
// ```
57+
pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
58+
generate_getter_impl(acc, ctx, true)
59+
}
60+
61+
pub(crate) fn generate_getter_impl(
62+
acc: &mut Assists,
63+
ctx: &AssistContext,
64+
mutable: bool,
65+
) -> Option<()> {
3266
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
3367
let field = ctx.find_node_at_offset::<ast::RecordField>()?;
3468

@@ -37,39 +71,45 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<
3771
let field_ty = field.ty()?;
3872

3973
// Return early if we've found an existing fn
40-
let fn_name = to_lower_snake_case(&field_name.to_string());
74+
let mut fn_name = to_lower_snake_case(&field_name.to_string());
75+
if mutable {
76+
format_to!(fn_name, "_mut");
77+
}
4178
let impl_def = find_struct_impl(&ctx, &ast::Adt::Struct(strukt.clone()), fn_name.as_str())?;
4279

80+
let (id, label) = if mutable {
81+
("generate_getter_mut", "Generate a mut getter method")
82+
} else {
83+
("generate_getter", "Generate a getter method")
84+
};
4385
let target = field.syntax().text_range();
4486
acc.add_group(
4587
&GroupLabel("Generate getter/setter".to_owned()),
46-
AssistId("generate_getter", AssistKind::Generate),
47-
"Generate a getter method",
88+
AssistId(id, AssistKind::Generate),
89+
label,
4890
target,
4991
|builder| {
5092
let mut buf = String::with_capacity(512);
5193

52-
let fn_name_spaced = fn_name.replace('_', " ");
53-
let strukt_name_spaced =
54-
to_lower_snake_case(&strukt_name.to_string()).replace('_', " ");
55-
5694
if impl_def.is_some() {
5795
buf.push('\n');
5896
}
5997

6098
let vis = strukt.visibility().map_or(String::new(), |v| format!("{} ", v));
6199
format_to!(
62100
buf,
63-
" /// Get a reference to the {}'s {}.
64-
{}fn {}(&self) -> &{} {{
65-
&self.{}
101+
" /// Get a {}reference to the {}'s {}.
102+
{}fn {}(&{mut_}self) -> &{mut_}{} {{
103+
&{mut_}self.{}
66104
}}",
67-
strukt_name_spaced,
68-
fn_name_spaced,
105+
mutable.then(|| "mutable ").unwrap_or_default(),
106+
to_lower_snake_case(&strukt_name.to_string()).replace('_', " "),
107+
fn_name.trim_end_matches("_mut").replace('_', " "),
69108
vis,
70109
fn_name,
71110
field_ty,
72-
fn_name,
111+
field_name,
112+
mut_ = mutable.then(|| "mut ").unwrap_or_default(),
73113
);
74114

75115
let start_offset = impl_def
@@ -79,7 +119,12 @@ pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext) -> Option<
79119
strukt.syntax().text_range().end()
80120
});
81121

82-
builder.insert(start_offset, buf);
122+
match ctx.config.snippet_cap {
123+
Some(cap) => {
124+
builder.insert_snippet(cap, start_offset, buf.replacen("fn ", "fn $0", 1))
125+
}
126+
None => builder.insert(start_offset, buf),
127+
}
83128
},
84129
)
85130
}
@@ -90,45 +135,81 @@ mod tests {
90135

91136
use super::*;
92137

93-
fn check_not_applicable(ra_fixture: &str) {
94-
check_assist_not_applicable(generate_getter, ra_fixture)
95-
}
96-
97138
#[test]
98139
fn test_generate_getter_from_field() {
99140
check_assist(
100141
generate_getter,
101142
r#"
102-
struct Context<T: Clone> {
103-
dat$0a: T,
104-
}"#,
143+
struct Context {
144+
dat$0a: Data,
145+
}
146+
"#,
105147
r#"
106-
struct Context<T: Clone> {
107-
data: T,
148+
struct Context {
149+
data: Data,
108150
}
109151
110-
impl<T: Clone> Context<T> {
152+
impl Context {
111153
/// Get a reference to the context's data.
112-
fn data(&self) -> &T {
154+
fn $0data(&self) -> &Data {
113155
&self.data
114156
}
115-
}"#,
157+
}
158+
"#,
159+
);
160+
161+
check_assist(
162+
generate_getter_mut,
163+
r#"
164+
struct Context {
165+
dat$0a: Data,
166+
}
167+
"#,
168+
r#"
169+
struct Context {
170+
data: Data,
171+
}
172+
173+
impl Context {
174+
/// Get a mutable reference to the context's data.
175+
fn $0data_mut(&mut self) -> &mut Data {
176+
&mut self.data
177+
}
178+
}
179+
"#,
116180
);
117181
}
118182

119183
#[test]
120184
fn test_generate_getter_already_implemented() {
121-
check_not_applicable(
185+
check_assist_not_applicable(
186+
generate_getter,
122187
r#"
123-
struct Context<T: Clone> {
124-
dat$0a: T,
188+
struct Context {
189+
dat$0a: Data,
125190
}
126191
127-
impl<T: Clone> Context<T> {
128-
fn data(&self) -> &T {
192+
impl Context {
193+
fn data(&self) -> &Data {
129194
&self.data
130195
}
131-
}"#,
196+
}
197+
"#,
198+
);
199+
200+
check_assist_not_applicable(
201+
generate_getter_mut,
202+
r#"
203+
struct Context {
204+
dat$0a: Data,
205+
}
206+
207+
impl Context {
208+
fn data_mut(&mut self) -> &mut Data {
209+
&mut self.data
210+
}
211+
}
212+
"#,
132213
);
133214
}
134215

@@ -137,20 +218,22 @@ impl<T: Clone> Context<T> {
137218
check_assist(
138219
generate_getter,
139220
r#"
140-
pub(crate) struct Context<T: Clone> {
141-
dat$0a: T,
142-
}"#,
221+
pub(crate) struct Context {
222+
dat$0a: Data,
223+
}
224+
"#,
143225
r#"
144-
pub(crate) struct Context<T: Clone> {
145-
data: T,
226+
pub(crate) struct Context {
227+
data: Data,
146228
}
147229
148-
impl<T: Clone> Context<T> {
230+
impl Context {
149231
/// Get a reference to the context's data.
150-
pub(crate) fn data(&self) -> &T {
232+
pub(crate) fn $0data(&self) -> &Data {
151233
&self.data
152234
}
153-
}"#,
235+
}
236+
"#,
154237
);
155238
}
156239

@@ -159,34 +242,36 @@ impl<T: Clone> Context<T> {
159242
check_assist(
160243
generate_getter,
161244
r#"
162-
struct Context<T: Clone> {
163-
data: T,
245+
struct Context {
246+
data: Data,
164247
cou$0nt: usize,
165248
}
166249
167-
impl<T: Clone> Context<T> {
250+
impl Context {
168251
/// Get a reference to the context's data.
169-
fn data(&self) -> &T {
252+
fn data(&self) -> &Data {
170253
&self.data
171254
}
172-
}"#,
255+
}
256+
"#,
173257
r#"
174-
struct Context<T: Clone> {
175-
data: T,
258+
struct Context {
259+
data: Data,
176260
count: usize,
177261
}
178262
179-
impl<T: Clone> Context<T> {
263+
impl Context {
180264
/// Get a reference to the context's data.
181-
fn data(&self) -> &T {
265+
fn data(&self) -> &Data {
182266
&self.data
183267
}
184268
185269
/// Get a reference to the context's count.
186-
fn count(&self) -> &usize {
270+
fn $0count(&self) -> &usize {
187271
&self.count
188272
}
189-
}"#,
273+
}
274+
"#,
190275
);
191276
}
192277
}

0 commit comments

Comments
 (0)