ide_assists/handlers/
generate_getter_or_setter.rs

1use ide_db::{famous_defs::FamousDefs, source_change::SourceChangeBuilder};
2use stdx::{format_to, to_lower_snake_case};
3use syntax::{
4    TextRange,
5    ast::{self, AstNode, HasName, HasVisibility, edit_in_place::Indent, make},
6    ted,
7};
8
9use crate::{
10    AssistContext, AssistId, Assists, GroupLabel,
11    utils::{convert_reference_type, find_struct_impl, generate_impl},
12};
13
14// Assist: generate_setter
15//
16// Generate a setter method.
17//
18// ```
19// struct Person {
20//     nam$0e: String,
21// }
22// ```
23// ->
24// ```
25// struct Person {
26//     name: String,
27// }
28//
29// impl Person {
30//     fn $0set_name(&mut self, name: String) {
31//         self.name = name;
32//     }
33// }
34// ```
35pub(crate) fn generate_setter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
36    // This if condition denotes two modes this assist can work in:
37    // - First is acting upon selection of record fields
38    // - Next is acting upon a single record field
39    //
40    // This is the only part where implementation diverges a bit,
41    // subsequent code is generic for both of these modes
42
43    let (strukt, info_of_record_fields, mut fn_names) = extract_and_parse(ctx, AssistType::Set)?;
44
45    // No record fields to do work on :(
46    if info_of_record_fields.is_empty() {
47        return None;
48    }
49
50    // Prepend set_ to fn names.
51    fn_names.iter_mut().for_each(|name| *name = format!("set_{name}"));
52
53    // Return early if we've found an existing fn
54    let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &fn_names)?;
55
56    // Computing collective text range of all record fields in selected region
57    let target: TextRange = info_of_record_fields
58        .iter()
59        .map(|record_field_info| record_field_info.target)
60        .reduce(|acc, target| acc.cover(target))?;
61
62    let setter_info = AssistInfo { impl_def, strukt, assist_type: AssistType::Set };
63
64    acc.add_group(
65        &GroupLabel("Generate getter/setter".to_owned()),
66        AssistId::generate("generate_setter"),
67        "Generate a setter method",
68        target,
69        |builder| build_source_change(builder, ctx, info_of_record_fields, setter_info),
70    );
71    Some(())
72}
73
74// Assist: generate_getter
75//
76// Generate a getter method.
77//
78// ```
79// # //- minicore: as_ref, deref
80// # pub struct String;
81// # impl AsRef<str> for String {
82// #     fn as_ref(&self) -> &str {
83// #         ""
84// #     }
85// # }
86// #
87// # impl core::ops::Deref for String {
88// #     type Target = str;
89// #     fn deref(&self) -> &Self::Target {
90// #         ""
91// #     }
92// # }
93// #
94// struct Person {
95//     nam$0e: String,
96// }
97// ```
98// ->
99// ```
100// # pub struct String;
101// # impl AsRef<str> for String {
102// #     fn as_ref(&self) -> &str {
103// #         ""
104// #     }
105// # }
106// #
107// # impl core::ops::Deref for String {
108// #     type Target = str;
109// #     fn deref(&self) -> &Self::Target {
110// #         ""
111// #     }
112// # }
113// #
114// struct Person {
115//     name: String,
116// }
117//
118// impl Person {
119//     fn $0name(&self) -> &str {
120//         &self.name
121//     }
122// }
123// ```
124pub(crate) fn generate_getter(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
125    generate_getter_impl(acc, ctx, false)
126}
127
128// Assist: generate_getter_mut
129//
130// Generate a mut getter method.
131//
132// ```
133// struct Person {
134//     nam$0e: String,
135// }
136// ```
137// ->
138// ```
139// struct Person {
140//     name: String,
141// }
142//
143// impl Person {
144//     fn $0name_mut(&mut self) -> &mut String {
145//         &mut self.name
146//     }
147// }
148// ```
149pub(crate) fn generate_getter_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
150    generate_getter_impl(acc, ctx, true)
151}
152
153#[derive(Clone, Debug)]
154struct RecordFieldInfo {
155    field_name: syntax::ast::Name,
156    field_ty: syntax::ast::Type,
157    fn_name: String,
158    target: TextRange,
159}
160
161struct AssistInfo {
162    impl_def: Option<ast::Impl>,
163    strukt: ast::Struct,
164    assist_type: AssistType,
165}
166
167enum AssistType {
168    Get,
169    MutGet,
170    Set,
171}
172
173pub(crate) fn generate_getter_impl(
174    acc: &mut Assists,
175    ctx: &AssistContext<'_>,
176    mutable: bool,
177) -> Option<()> {
178    let (strukt, info_of_record_fields, fn_names) =
179        extract_and_parse(ctx, if mutable { AssistType::MutGet } else { AssistType::Get })?;
180    // No record fields to do work on :(
181    if info_of_record_fields.is_empty() {
182        return None;
183    }
184
185    let impl_def = find_struct_impl(ctx, &ast::Adt::Struct(strukt.clone()), &fn_names)?;
186
187    let (id, label) = if mutable {
188        ("generate_getter_mut", "Generate a mut getter method")
189    } else {
190        ("generate_getter", "Generate a getter method")
191    };
192
193    // Computing collective text range of all record fields in selected region
194    let target: TextRange = info_of_record_fields
195        .iter()
196        .map(|record_field_info| record_field_info.target)
197        .reduce(|acc, target| acc.cover(target))?;
198
199    let getter_info = AssistInfo {
200        impl_def,
201        strukt,
202        assist_type: if mutable { AssistType::MutGet } else { AssistType::Get },
203    };
204
205    acc.add_group(
206        &GroupLabel("Generate getter/setter".to_owned()),
207        AssistId::generate(id),
208        label,
209        target,
210        |builder| build_source_change(builder, ctx, info_of_record_fields, getter_info),
211    )
212}
213
214fn generate_getter_from_info(
215    ctx: &AssistContext<'_>,
216    info: &AssistInfo,
217    record_field_info: &RecordFieldInfo,
218) -> ast::Fn {
219    let (ty, body) = if matches!(info.assist_type, AssistType::MutGet) {
220        (
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()),
224                true,
225            ),
226        )
227    } else {
228        (|| {
229            let krate = ctx.sema.scope(record_field_info.field_ty.syntax())?.krate();
230            let famous_defs = &FamousDefs(&ctx.sema, krate);
231            ctx.sema
232                .resolve_type(&record_field_info.field_ty)
233                .and_then(|ty| convert_reference_type(ty, ctx.db(), famous_defs))
234                .map(|conversion| {
235                    cov_mark::hit!(convert_reference_type);
236                    (
237                        conversion.convert_type(ctx.db(), krate.to_display_target(ctx.db())),
238                        conversion.getter(record_field_info.field_name.to_string()),
239                    )
240                })
241        })()
242        .unwrap_or_else(|| {
243            (
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()),
247                    false,
248                ),
249            )
250        })
251    };
252
253    let self_param = if matches!(info.assist_type, AssistType::MutGet) {
254        make::mut_self_param()
255    } else {
256        make::self_param()
257    };
258
259    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));
264
265    make::fn_(
266        None,
267        strukt.visibility(),
268        fn_name,
269        None,
270        None,
271        params,
272        body,
273        ret_type,
274        false,
275        false,
276        false,
277        false,
278    )
279}
280
281fn generate_setter_from_info(info: &AssistInfo, record_field_info: &RecordFieldInfo) -> ast::Fn {
282    let strukt = &info.strukt;
283    let field_name = &record_field_info.fn_name;
284    let fn_name = make::name(&format!("set_{field_name}"));
285    let field_ty = &record_field_info.field_ty;
286
287    // Make the param list
288    // `(&mut self, $field_name: $field_ty)`
289    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]);
292
293    // Make the assignment body
294    // `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);
300
301    // Make the setter fn
302    make::fn_(
303        None,
304        strukt.visibility(),
305        fn_name,
306        None,
307        None,
308        params,
309        body,
310        None,
311        false,
312        false,
313        false,
314        false,
315    )
316}
317
318fn extract_and_parse(
319    ctx: &AssistContext<'_>,
320    assist_type: AssistType,
321) -> Option<(ast::Struct, Vec<RecordFieldInfo>, Vec<String>)> {
322    // This if condition denotes two modes assists can work in:
323    // - First is acting upon selection of record fields
324    // - Next is acting upon a single record field
325    if !ctx.has_empty_selection() {
326        // Selection Mode
327        let node = ctx.covering_element();
328
329        let node = match node {
330            syntax::NodeOrToken::Node(n) => n,
331            syntax::NodeOrToken::Token(t) => t.parent()?,
332        };
333
334        let parent_struct = node.ancestors().find_map(ast::Struct::cast)?;
335
336        let (info_of_record_fields, field_names) =
337            extract_and_parse_record_fields(&parent_struct, ctx.selection_trimmed(), &assist_type)?;
338
339        return Some((parent_struct, info_of_record_fields, field_names));
340    }
341
342    // Single Record Field mode
343    let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
344    let field = ctx.find_node_at_offset::<ast::RecordField>()?;
345    let record_field_info = parse_record_field(field, &assist_type)?;
346    let fn_name = record_field_info.fn_name.clone();
347    Some((strukt, vec![record_field_info], vec![fn_name]))
348}
349
350fn extract_and_parse_record_fields(
351    node: &ast::Struct,
352    selection_range: TextRange,
353    assist_type: &AssistType,
354) -> Option<(Vec<RecordFieldInfo>, Vec<String>)> {
355    let mut field_names: Vec<String> = vec![];
356    let field_list = node.field_list()?;
357
358    match field_list {
359        ast::FieldList::RecordFieldList(ele) => {
360            let info_of_record_fields_in_selection = ele
361                .fields()
362                .filter_map(|record_field| {
363                    if selection_range.contains_range(record_field.syntax().text_range()) {
364                        let record_field_info = parse_record_field(record_field, assist_type)?;
365                        field_names.push(record_field_info.fn_name.clone());
366                        return Some(record_field_info);
367                    }
368
369                    None
370                })
371                .collect::<Vec<RecordFieldInfo>>();
372
373            if info_of_record_fields_in_selection.is_empty() {
374                return None;
375            }
376
377            Some((info_of_record_fields_in_selection, field_names))
378        }
379        ast::FieldList::TupleFieldList(_) => None,
380    }
381}
382
383fn parse_record_field(
384    record_field: ast::RecordField,
385    assist_type: &AssistType,
386) -> Option<RecordFieldInfo> {
387    let field_name = record_field.name()?;
388    let field_ty = record_field.ty()?;
389
390    let mut fn_name = to_lower_snake_case(&field_name.to_string());
391    if matches!(assist_type, AssistType::MutGet) {
392        format_to!(fn_name, "_mut");
393    }
394
395    let target = record_field.syntax().text_range();
396
397    Some(RecordFieldInfo { field_name, field_ty, fn_name, target })
398}
399
400fn build_source_change(
401    builder: &mut SourceChangeBuilder,
402    ctx: &AssistContext<'_>,
403    info_of_record_fields: Vec<RecordFieldInfo>,
404    assist_info: AssistInfo,
405) {
406    let record_fields_count = info_of_record_fields.len();
407
408    let impl_def = if let Some(impl_def) = &assist_info.impl_def {
409        // 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());
417
418        ted::insert_all_raw(
419            ted::Position::after(strukt.syntax()),
420            vec![make::tokens::blank_line().into(), impl_def.syntax().clone().into()],
421        );
422
423        impl_def
424    };
425
426    let assoc_item_list = impl_def.get_or_create_assoc_item_list();
427
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);
443        }
444
445        assoc_item_list.add_item(new_fn.clone().into());
446    }
447}
448
449#[cfg(test)]
450mod tests_getter {
451    use crate::tests::{check_assist, check_assist_no_snippet_cap, check_assist_not_applicable};
452
453    use super::*;
454
455    #[test]
456    fn test_generate_getter_from_field() {
457        check_assist(
458            generate_getter,
459            r#"
460struct Context {
461    dat$0a: Data,
462}
463"#,
464            r#"
465struct Context {
466    data: Data,
467}
468
469impl Context {
470    fn $0data(&self) -> &Data {
471        &self.data
472    }
473}
474"#,
475        );
476
477        check_assist(
478            generate_getter_mut,
479            r#"
480struct Context {
481    dat$0a: Data,
482}
483"#,
484            r#"
485struct Context {
486    data: Data,
487}
488
489impl Context {
490    fn $0data_mut(&mut self) -> &mut Data {
491        &mut self.data
492    }
493}
494"#,
495        );
496    }
497
498    #[test]
499    fn test_generate_getter_from_field_no_snippet_cap() {
500        check_assist_no_snippet_cap(
501            generate_getter,
502            r#"
503struct Context {
504    dat$0a: Data,
505}
506"#,
507            r#"
508struct Context {
509    data: Data,
510}
511
512impl Context {
513    fn data(&self) -> &Data {
514        &self.data
515    }
516}
517"#,
518        );
519
520        check_assist_no_snippet_cap(
521            generate_getter_mut,
522            r#"
523struct Context {
524    dat$0a: Data,
525}
526"#,
527            r#"
528struct Context {
529    data: Data,
530}
531
532impl Context {
533    fn data_mut(&mut self) -> &mut Data {
534        &mut self.data
535    }
536}
537"#,
538        );
539    }
540
541    #[test]
542    fn test_generate_getter_already_implemented() {
543        check_assist_not_applicable(
544            generate_getter,
545            r#"
546struct Context {
547    dat$0a: Data,
548}
549
550impl Context {
551    fn data(&self) -> &Data {
552        &self.data
553    }
554}
555"#,
556        );
557
558        check_assist_not_applicable(
559            generate_getter_mut,
560            r#"
561struct Context {
562    dat$0a: Data,
563}
564
565impl Context {
566    fn data_mut(&mut self) -> &mut Data {
567        &mut self.data
568    }
569}
570"#,
571        );
572    }
573
574    #[test]
575    fn test_generate_getter_from_field_with_visibility_marker() {
576        check_assist(
577            generate_getter,
578            r#"
579pub(crate) struct Context {
580    dat$0a: Data,
581}
582"#,
583            r#"
584pub(crate) struct Context {
585    data: Data,
586}
587
588impl Context {
589    pub(crate) fn $0data(&self) -> &Data {
590        &self.data
591    }
592}
593"#,
594        );
595    }
596
597    #[test]
598    fn test_generate_getter_from_field_with_visibility_marker_no_snippet_cap() {
599        check_assist_no_snippet_cap(
600            generate_getter,
601            r#"
602pub(crate) struct Context {
603    dat$0a: Data,
604}
605"#,
606            r#"
607pub(crate) struct Context {
608    data: Data,
609}
610
611impl Context {
612    pub(crate) fn data(&self) -> &Data {
613        &self.data
614    }
615}
616"#,
617        );
618    }
619
620    #[test]
621    fn test_multiple_generate_getter() {
622        check_assist(
623            generate_getter,
624            r#"
625struct Context {
626    data: Data,
627    cou$0nt: usize,
628}
629
630impl Context {
631    fn data(&self) -> &Data {
632        &self.data
633    }
634}
635"#,
636            r#"
637struct Context {
638    data: Data,
639    count: usize,
640}
641
642impl Context {
643    fn data(&self) -> &Data {
644        &self.data
645    }
646
647    fn $0count(&self) -> &usize {
648        &self.count
649    }
650}
651"#,
652        );
653    }
654
655    #[test]
656    fn test_multiple_generate_getter_no_snippet_cap() {
657        check_assist_no_snippet_cap(
658            generate_getter,
659            r#"
660struct Context {
661    data: Data,
662    cou$0nt: usize,
663}
664
665impl Context {
666    fn data(&self) -> &Data {
667        &self.data
668    }
669}
670"#,
671            r#"
672struct Context {
673    data: Data,
674    count: usize,
675}
676
677impl Context {
678    fn data(&self) -> &Data {
679        &self.data
680    }
681
682    fn count(&self) -> &usize {
683        &self.count
684    }
685}
686"#,
687        );
688    }
689
690    #[test]
691    fn test_not_a_special_case() {
692        cov_mark::check_count!(convert_reference_type, 0);
693        // Fake string which doesn't implement AsRef<str>
694        check_assist(
695            generate_getter,
696            r#"
697pub struct String;
698
699struct S { foo: $0String }
700"#,
701            r#"
702pub struct String;
703
704struct S { foo: String }
705
706impl S {
707    fn $0foo(&self) -> &String {
708        &self.foo
709    }
710}
711"#,
712        );
713    }
714
715    #[test]
716    fn test_convert_reference_type() {
717        cov_mark::check_count!(convert_reference_type, 6);
718
719        // Copy
720        check_assist(
721            generate_getter,
722            r#"
723//- minicore: copy
724struct S { foo: $0bool }
725"#,
726            r#"
727struct S { foo: bool }
728
729impl S {
730    fn $0foo(&self) -> bool {
731        self.foo
732    }
733}
734"#,
735        );
736
737        // AsRef<str>
738        check_assist(
739            generate_getter,
740            r#"
741//- minicore: as_ref
742pub struct String;
743impl AsRef<str> for String {
744    fn as_ref(&self) -> &str {
745        ""
746    }
747}
748
749struct S { foo: $0String }
750"#,
751            r#"
752pub struct String;
753impl AsRef<str> for String {
754    fn as_ref(&self) -> &str {
755        ""
756    }
757}
758
759struct S { foo: String }
760
761impl S {
762    fn $0foo(&self) -> &str {
763        self.foo.as_ref()
764    }
765}
766"#,
767        );
768
769        // AsRef<T>
770        check_assist(
771            generate_getter,
772            r#"
773//- minicore: as_ref
774struct Sweets;
775
776pub struct Box<T>(T);
777impl<T> AsRef<T> for Box<T> {
778    fn as_ref(&self) -> &T {
779        &self.0
780    }
781}
782
783struct S { foo: $0Box<Sweets> }
784"#,
785            r#"
786struct Sweets;
787
788pub struct Box<T>(T);
789impl<T> AsRef<T> for Box<T> {
790    fn as_ref(&self) -> &T {
791        &self.0
792    }
793}
794
795struct S { foo: Box<Sweets> }
796
797impl S {
798    fn $0foo(&self) -> &Sweets {
799        self.foo.as_ref()
800    }
801}
802"#,
803        );
804
805        // AsRef<[T]>
806        check_assist(
807            generate_getter,
808            r#"
809//- minicore: as_ref
810pub struct Vec<T>;
811impl<T> AsRef<[T]> for Vec<T> {
812    fn as_ref(&self) -> &[T] {
813        &[]
814    }
815}
816
817struct S { foo: $0Vec<()> }
818"#,
819            r#"
820pub struct Vec<T>;
821impl<T> AsRef<[T]> for Vec<T> {
822    fn as_ref(&self) -> &[T] {
823        &[]
824    }
825}
826
827struct S { foo: Vec<()> }
828
829impl S {
830    fn $0foo(&self) -> &[()] {
831        self.foo.as_ref()
832    }
833}
834"#,
835        );
836
837        // Option
838        check_assist(
839            generate_getter,
840            r#"
841//- minicore: option
842struct Failure;
843
844struct S { foo: $0Option<Failure> }
845"#,
846            r#"
847struct Failure;
848
849struct S { foo: Option<Failure> }
850
851impl S {
852    fn $0foo(&self) -> Option<&Failure> {
853        self.foo.as_ref()
854    }
855}
856"#,
857        );
858
859        // Result
860        check_assist(
861            generate_getter,
862            r#"
863//- minicore: result
864struct Context {
865    dat$0a: Result<bool, i32>,
866}
867"#,
868            r#"
869struct Context {
870    data: Result<bool, i32>,
871}
872
873impl Context {
874    fn $0data(&self) -> Result<&bool, &i32> {
875        self.data.as_ref()
876    }
877}
878"#,
879        );
880    }
881
882    #[test]
883    fn test_generate_multiple_getters_from_selection() {
884        check_assist(
885            generate_getter,
886            r#"
887struct Context {
888    $0data: Data,
889    count: usize,$0
890}
891    "#,
892            r#"
893struct Context {
894    data: Data,
895    count: usize,
896}
897
898impl Context {
899    fn data(&self) -> &Data {
900        &self.data
901    }
902
903    fn $0count(&self) -> &usize {
904        &self.count
905    }
906}
907    "#,
908        );
909    }
910
911    #[test]
912    fn test_generate_multiple_getters_from_selection_one_already_exists() {
913        // As impl for one of the fields already exist, skip it
914        check_assist_not_applicable(
915            generate_getter,
916            r#"
917struct Context {
918    $0data: Data,
919    count: usize,$0
920}
921
922impl Context {
923    fn data(&self) -> &Data {
924        &self.data
925    }
926}
927    "#,
928        );
929    }
930}
931
932#[cfg(test)]
933mod tests_setter {
934    use crate::tests::{check_assist, check_assist_not_applicable};
935
936    use super::*;
937
938    fn check_not_applicable(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
939        check_assist_not_applicable(generate_setter, ra_fixture)
940    }
941
942    #[test]
943    fn test_generate_setter_from_field() {
944        check_assist(
945            generate_setter,
946            r#"
947struct Person<T: Clone> {
948    dat$0a: T,
949}"#,
950            r#"
951struct Person<T: Clone> {
952    data: T,
953}
954
955impl<T: Clone> Person<T> {
956    fn $0set_data(&mut self, data: T) {
957        self.data = data;
958    }
959}"#,
960        );
961    }
962
963    #[test]
964    fn test_generate_setter_already_implemented() {
965        check_not_applicable(
966            r#"
967struct Person<T: Clone> {
968    dat$0a: T,
969}
970
971impl<T: Clone> Person<T> {
972    fn set_data(&mut self, data: T) {
973        self.data = data;
974    }
975}"#,
976        );
977    }
978
979    #[test]
980    fn test_generate_setter_from_field_with_visibility_marker() {
981        check_assist(
982            generate_setter,
983            r#"
984pub(crate) struct Person<T: Clone> {
985    dat$0a: T,
986}"#,
987            r#"
988pub(crate) struct Person<T: Clone> {
989    data: T,
990}
991
992impl<T: Clone> Person<T> {
993    pub(crate) fn $0set_data(&mut self, data: T) {
994        self.data = data;
995    }
996}"#,
997        );
998    }
999
1000    #[test]
1001    fn test_multiple_generate_setter() {
1002        check_assist(
1003            generate_setter,
1004            r#"
1005struct Context<T: Clone> {
1006    data: T,
1007    cou$0nt: usize,
1008}
1009
1010impl<T: Clone> Context<T> {
1011    fn set_data(&mut self, data: T) {
1012        self.data = data;
1013    }
1014}"#,
1015            r#"
1016struct Context<T: Clone> {
1017    data: T,
1018    count: usize,
1019}
1020
1021impl<T: Clone> Context<T> {
1022    fn set_data(&mut self, data: T) {
1023        self.data = data;
1024    }
1025
1026    fn $0set_count(&mut self, count: usize) {
1027        self.count = count;
1028    }
1029}"#,
1030        );
1031    }
1032}