Skip to content

Commit dd91292

Browse files
committed
internal: migrate generate_getter_or_setter to SyntaxEditor api
1 parent adc173c commit dd91292

File tree

1 file changed

+90
-58
lines changed

1 file changed

+90
-58
lines changed

crates/ide-assists/src/handlers/generate_getter_or_setter.rs

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ use ide_db::{famous_defs::FamousDefs, source_change::SourceChangeBuilder};
22
use stdx::{format_to, to_lower_snake_case};
33
use syntax::{
44
TextRange,
5-
ast::{self, AstNode, HasName, HasVisibility, edit_in_place::Indent, make},
6-
ted,
5+
ast::{
6+
self, AstNode, HasGenericParams, HasName, HasVisibility, edit_in_place::Indent,
7+
syntax_factory::SyntaxFactory,
8+
},
9+
syntax_editor::Position,
710
};
811

912
use crate::{
1013
AssistContext, AssistId, Assists, GroupLabel,
11-
utils::{convert_reference_type, find_struct_impl, generate_impl},
14+
utils::{convert_reference_type, find_struct_impl},
1215
};
1316

1417
// Assist: generate_setter
@@ -216,11 +219,14 @@ fn generate_getter_from_info(
216219
info: &AssistInfo,
217220
record_field_info: &RecordFieldInfo,
218221
) -> ast::Fn {
222+
let make = SyntaxFactory::without_mappings();
223+
219224
let (ty, body) = if matches!(info.assist_type, AssistType::MutGet) {
225+
let self_expr = make.expr_path(make.ident_path("self"));
220226
(
221-
make::ty_ref(record_field_info.field_ty.clone(), true),
222-
make::expr_ref(
223-
make::expr_field(make::ext::expr_self(), &record_field_info.field_name.text()),
227+
make.ty_ref(record_field_info.field_ty.clone(), true),
228+
make.expr_ref(
229+
make.expr_field(self_expr, &record_field_info.field_name.text()).into(),
224230
true,
225231
),
226232
)
@@ -240,29 +246,30 @@ fn generate_getter_from_info(
240246
})
241247
})()
242248
.unwrap_or_else(|| {
249+
let self_expr = make.expr_path(make.ident_path("self"));
243250
(
244-
make::ty_ref(record_field_info.field_ty.clone(), false),
245-
make::expr_ref(
246-
make::expr_field(make::ext::expr_self(), &record_field_info.field_name.text()),
251+
make.ty_ref(record_field_info.field_ty.clone(), false),
252+
make.expr_ref(
253+
make.expr_field(self_expr, &record_field_info.field_name.text()).into(),
247254
false,
248255
),
249256
)
250257
})
251258
};
252259

253260
let self_param = if matches!(info.assist_type, AssistType::MutGet) {
254-
make::mut_self_param()
261+
make.mut_self_param()
255262
} else {
256-
make::self_param()
263+
make.self_param()
257264
};
258265

259266
let strukt = &info.strukt;
260-
let fn_name = make::name(&record_field_info.fn_name);
261-
let params = make::param_list(Some(self_param), []);
262-
let ret_type = Some(make::ret_type(ty));
263-
let body = make::block_expr([], Some(body));
267+
let fn_name = make.name(&record_field_info.fn_name);
268+
let params = make.param_list(Some(self_param), []);
269+
let ret_type = Some(make.ret_type(ty));
270+
let body = make.block_expr([], Some(body));
264271

265-
make::fn_(
272+
make.fn_(
266273
None,
267274
strukt.visibility(),
268275
fn_name,
@@ -277,29 +284,30 @@ fn generate_getter_from_info(
277284
false,
278285
)
279286
}
280-
281287
fn generate_setter_from_info(info: &AssistInfo, record_field_info: &RecordFieldInfo) -> ast::Fn {
288+
let make = SyntaxFactory::without_mappings();
289+
282290
let strukt = &info.strukt;
283291
let field_name = &record_field_info.fn_name;
284-
let fn_name = make::name(&format!("set_{field_name}"));
292+
let fn_name = make.name(&format!("set_{field_name}"));
285293
let field_ty = &record_field_info.field_ty;
286294

287295
// Make the param list
288296
// `(&mut self, $field_name: $field_ty)`
289297
let field_param =
290-
make::param(make::ident_pat(false, false, make::name(field_name)).into(), field_ty.clone());
291-
let params = make::param_list(Some(make::mut_self_param()), [field_param]);
298+
make.param(make.ident_pat(false, false, make.name(field_name)).into(), field_ty.clone());
299+
let params = make.param_list(Some(make.mut_self_param()), [field_param]);
292300

293301
// Make the assignment body
294302
// `self.$field_name = $field_name`
295-
let self_expr = make::ext::expr_self();
296-
let lhs = make::expr_field(self_expr, field_name);
297-
let rhs = make::expr_path(make::ext::ident_path(field_name));
298-
let assign_stmt = make::expr_stmt(make::expr_assignment(lhs, rhs).into());
299-
let body = make::block_expr([assign_stmt.into()], None);
303+
let self_expr = make.expr_path(make.ident_path("self"));
304+
let lhs = make.expr_field(self_expr, field_name);
305+
let rhs = make.expr_path(make.ident_path(field_name));
306+
let assign_stmt = make.expr_stmt(make.expr_assignment(lhs.into(), rhs).into());
307+
let body = make.block_expr([assign_stmt.into()], None);
300308

301309
// Make the setter fn
302-
make::fn_(
310+
make.fn_(
303311
None,
304312
strukt.visibility(),
305313
fn_name,
@@ -403,46 +411,70 @@ fn build_source_change(
403411
info_of_record_fields: Vec<RecordFieldInfo>,
404412
assist_info: AssistInfo,
405413
) {
406-
let record_fields_count = info_of_record_fields.len();
414+
let items: Vec<ast::AssocItem> = info_of_record_fields
415+
.iter()
416+
.map(|record_field_info| {
417+
let method = match assist_info.assist_type {
418+
AssistType::Set => generate_setter_from_info(&assist_info, record_field_info),
419+
_ => generate_getter_from_info(ctx, &assist_info, record_field_info),
420+
};
421+
let new_fn = method.clone_for_update();
422+
new_fn.indent(1.into());
423+
new_fn.into()
424+
})
425+
.collect();
407426

408-
let impl_def = if let Some(impl_def) = &assist_info.impl_def {
427+
if let Some(impl_def) = &assist_info.impl_def {
409428
// We have an existing impl to add to
410-
builder.make_mut(impl_def.clone())
411-
} else {
412-
// Generate a new impl to add the methods to
413-
let impl_def = generate_impl(&ast::Adt::Struct(assist_info.strukt.clone()));
414-
415-
// Insert it after the adt
416-
let strukt = builder.make_mut(assist_info.strukt.clone());
429+
let mut editor = builder.make_editor(impl_def.syntax());
430+
431+
let assoc_item_list = impl_def.assoc_item_list().unwrap();
432+
assoc_item_list.add_items(&mut editor, items.clone());
433+
434+
// Add tabstop for last method
435+
if let Some(cap) = ctx.config.snippet_cap {
436+
if let Some(ast::AssocItem::Fn(fn_)) = items.last() {
437+
if let Some(name) = fn_.name() {
438+
let tabstop = builder.make_tabstop_before(cap);
439+
editor.add_annotation(name.syntax().clone(), tabstop);
440+
}
441+
}
442+
}
417443

418-
ted::insert_all_raw(
419-
ted::Position::after(strukt.syntax()),
420-
vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
444+
builder.add_file_edits(ctx.vfs_file_id(), editor);
445+
} else {
446+
let make = SyntaxFactory::without_mappings();
447+
let ty_params = assist_info.strukt.generic_param_list();
448+
let ty_args = ty_params.as_ref().map(|it| it.to_generic_args());
449+
let impl_def = make.impl_(
450+
None,
451+
ty_params,
452+
ty_args,
453+
make.ty_path(make.ident_path(&assist_info.strukt.name().unwrap().to_string())).into(),
454+
None,
455+
Some(make.assoc_item_list(items)),
421456
);
422457

423-
impl_def
424-
};
425-
426-
let assoc_item_list = impl_def.get_or_create_assoc_item_list();
458+
let mut editor = builder.make_editor(assist_info.strukt.syntax());
459+
// Insert impl after the struct
460+
editor.insert_all(
461+
Position::after(assist_info.strukt.syntax()),
462+
vec![make.whitespace("\n\n").into(), impl_def.syntax().clone().into()],
463+
);
427464

428-
for (i, record_field_info) in info_of_record_fields.iter().enumerate() {
429-
// Make the new getter or setter fn
430-
let new_fn = match assist_info.assist_type {
431-
AssistType::Set => generate_setter_from_info(&assist_info, record_field_info),
432-
_ => generate_getter_from_info(ctx, &assist_info, record_field_info),
433-
}
434-
.clone_for_update();
435-
new_fn.indent(1.into());
436-
437-
// Insert a tabstop only for last method we generate
438-
if i == record_fields_count - 1
439-
&& let Some(cap) = ctx.config.snippet_cap
440-
&& let Some(name) = new_fn.name()
441-
{
442-
builder.add_tabstop_before(cap, name);
465+
// Add tabstop for last method
466+
if let Some(cap) = ctx.config.snippet_cap {
467+
if let Some(assoc_list) = impl_def.assoc_item_list() {
468+
if let Some(ast::AssocItem::Fn(fn_)) = assoc_list.assoc_items().last() {
469+
if let Some(name) = fn_.name() {
470+
let tabstop = builder.make_tabstop_before(cap);
471+
editor.add_annotation(name.syntax().clone(), tabstop);
472+
}
473+
}
474+
}
443475
}
444476

445-
assoc_item_list.add_item(new_fn.clone().into());
477+
builder.add_file_edits(ctx.vfs_file_id(), editor);
446478
}
447479
}
448480

0 commit comments

Comments
 (0)