1 use stdx::{format_to, to_lower_snake_case};
2 use syntax::ast::{self, AstNode, HasName, HasVisibility};
5 utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
6 AssistContext, AssistId, AssistKind, Assists, GroupLabel,
9 // Assist: generate_setter
11 // Generate a setter method.
25 // fn set_name(&mut self, name: String) {
30 pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
31 let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
32 let field = ctx.find_node_at_offset::<ast::RecordField>()?;
34 let field_name = field.name()?;
35 let field_ty = field.ty()?;
37 // Return early if we've found an existing fn
38 let fn_name = to_lower_snake_case(&field_name.to_string());
40 find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &[format!("set_{fn_name}")])?;
42 let target = field.syntax().text_range();
44 &GroupLabel("Generate getter/setter".to_owned()),
45 AssistId("generate_setter", AssistKind::Generate),
46 "Generate a setter method",
49 let mut buf = String::with_capacity(512);
51 if impl_def.is_some() {
55 let vis = strukt.visibility().map_or(String::new(), |v| format!("{v} "));
58 " {vis}fn set_{fn_name}(&mut self, {fn_name}: {field_ty}) {{
59 self.{fn_name} = {fn_name};
63 let start_offset = impl_def
64 .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
66 buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf);
67 strukt.syntax().text_range().end()
70 builder.insert(start_offset, buf);
77 use crate::tests::{check_assist, check_assist_not_applicable};
81 fn check_not_applicable(ra_fixture: &str) {
82 check_assist_not_applicable(generate_setter, ra_fixture)
86 fn test_generate_setter_from_field() {
90 struct Person<T: Clone> {
94 struct Person<T: Clone> {
98 impl<T: Clone> Person<T> {
99 fn set_data(&mut self, data: T) {
107 fn test_generate_setter_already_implemented() {
108 check_not_applicable(
110 struct Person<T: Clone> {
114 impl<T: Clone> Person<T> {
115 fn set_data(&mut self, data: T) {
123 fn test_generate_setter_from_field_with_visibility_marker() {
127 pub(crate) struct Person<T: Clone> {
131 pub(crate) struct Person<T: Clone> {
135 impl<T: Clone> Person<T> {
136 pub(crate) fn set_data(&mut self, data: T) {
144 fn test_multiple_generate_setter() {
148 struct Context<T: Clone> {
153 impl<T: Clone> Context<T> {
154 fn set_data(&mut self, data: T) {
159 struct Context<T: Clone> {
164 impl<T: Clone> Context<T> {
165 fn set_data(&mut self, data: T) {
169 fn set_count(&mut self, count: usize) {