1use hir::next_solver::{DbInterner, TypingMode};
2use hir::{HasCrate, ModuleDef, Semantics};
3use ide_db::use_trivial_constructor::use_trivial_constructor_with_factory;
4use ide_db::{
5 RootDatabase, famous_defs::FamousDefs, helpers::mod_path_to_ast_with_factory,
6 imports::import_assets::item_for_path_search,
7};
8use syntax::syntax_editor::{Position, SyntaxEditor};
9use syntax::{
10 TokenText,
11 ast::{
12 self, AstNode, HasAttrs, HasGenericParams, HasName, edit::AstNodeEdit,
13 syntax_factory::SyntaxFactory,
14 },
15};
16
17use crate::{
18 AssistId,
19 assist_context::{AssistContext, Assists},
20};
21
22pub(crate) fn generate_single_field_struct_from(
49 acc: &mut Assists,
50 ctx: &AssistContext<'_, '_>,
51) -> Option<()> {
52 let strukt_name = ctx.find_node_at_offset::<ast::Name>()?;
53 let adt = ast::Adt::cast(strukt_name.syntax().parent()?)?;
54 let ast::Adt::Struct(strukt) = adt else {
55 tracing::debug!(?adt);
56 return None;
57 };
58
59 let sema = &ctx.sema;
60 let (names, types) = get_fields(&strukt)?;
61
62 let module = sema.scope(strukt.syntax())?.module();
63 let constructors = make_constructors(ctx, module, &types);
64
65 if constructors.iter().filter(|expr| expr.is_none()).count() != 1 {
66 tracing::debug!(?constructors);
67 return None;
68 }
69 let main_field_i = constructors.iter().position(Option::is_none)?;
70 if from_impl_exists(&strukt, main_field_i, &ctx.sema).is_some() {
71 tracing::debug!(?strukt, ?main_field_i);
72 return None;
73 }
74
75 let main_field_name =
76 names.as_ref().map_or(TokenText::borrowed("value"), |names| names[main_field_i].text());
77 let main_field_ty = types[main_field_i].clone();
78
79 acc.add(
80 AssistId::generate("generate_single_field_struct_from"),
81 "Generate single field `From`",
82 strukt.syntax().text_range(),
83 |builder| {
84 let editor = builder.make_editor(strukt.syntax());
85 let make = editor.make();
86
87 let indent = strukt.indent_level();
88 let ty_where_clause = strukt.where_clause();
89 let type_gen_params = strukt.generic_param_list();
90 let type_gen_args = type_gen_params.as_ref().map(|params| params.to_generic_args(make));
91 let trait_gen_args = Some(make.generic_arg_list(
92 [ast::GenericArg::TypeArg(make.type_arg(main_field_ty.clone()))],
93 false,
94 ));
95
96 let ty = make.ty(&strukt_name.text());
97
98 let constructor =
99 make_adt_constructor(names.as_deref(), constructors, &main_field_name, make);
100 let body = make.block_expr([], Some(constructor));
101
102 let fn_ = make
103 .fn_(
104 [],
105 None,
106 make.name("from"),
107 None,
108 None,
109 make.param_list(
110 None,
111 [make.param(
112 make.path_pat(make.path_from_text(&main_field_name)),
113 main_field_ty,
114 )],
115 ),
116 body,
117 Some(make.ret_type(make.ty("Self"))),
118 false,
119 false,
120 false,
121 false,
122 )
123 .indent_with_mapping(1.into(), make);
124
125 let cfg_attrs =
126 strukt.attrs().filter(|attr| matches!(attr.meta(), Some(ast::Meta::CfgMeta(_))));
127
128 let impl_ = make.impl_trait(
129 cfg_attrs,
130 false,
131 None,
132 trait_gen_args,
133 type_gen_params,
134 type_gen_args,
135 false,
136 make.ty("From"),
137 ty.clone(),
138 None,
139 ty_where_clause.map(|wc| wc.reset_indent()),
140 None,
141 );
142
143 let (impl_editor, impl_root) = SyntaxEditor::with_ast_node(&impl_);
144 let assoc_list = impl_root.get_or_create_assoc_item_list_with_editor(&impl_editor);
145 assoc_list.add_items(&impl_editor, vec![fn_.into()]);
146 let impl_ = ast::Impl::cast(impl_editor.finish().new_root().clone())
147 .unwrap()
148 .indent_with_mapping(indent, make);
149
150 editor.insert_all(
151 Position::after(strukt.syntax()),
152 vec![
153 make.whitespace(&format!("\n\n{indent}")).into(),
154 impl_.syntax().clone().into(),
155 ],
156 );
157 builder.add_file_edits(ctx.vfs_file_id(), editor);
158 },
159 )
160}
161
162fn make_adt_constructor(
163 names: Option<&[ast::Name]>,
164 constructors: Vec<Option<ast::Expr>>,
165 main_field_name: &TokenText<'_>,
166 make: &SyntaxFactory,
167) -> ast::Expr {
168 if let Some(names) = names {
169 let fields = make.record_expr_field_list(names.iter().zip(constructors).map(
170 |(name, initializer)| make.record_expr_field(make.name_ref(&name.text()), initializer),
171 ));
172 make.record_expr(make.path_from_text("Self"), fields).into()
173 } else {
174 let arg_list = make.arg_list(constructors.into_iter().map(|expr| {
175 expr.unwrap_or_else(|| make.expr_path(make.path_from_text(main_field_name)))
176 }));
177 make.expr_call(make.expr_path(make.path_from_text("Self")), arg_list).into()
178 }
179}
180
181fn make_constructors(
182 ctx: &AssistContext<'_, '_>,
183 module: hir::Module,
184 types: &[ast::Type],
185) -> Vec<Option<ast::Expr>> {
186 let make = SyntaxFactory::without_mappings();
187 let (db, sema) = (ctx.db(), &ctx.sema);
188 let cfg = ctx.config.find_path_config(ctx.sema.is_nightly(module.krate(ctx.sema.db)));
189 types
190 .iter()
191 .map(|ty| {
192 let ty = sema.resolve_type(ty)?;
193 if ty.is_unit() {
194 return Some(make.expr_tuple([]).into());
195 }
196 let item_in_ns = ModuleDef::Adt(ty.as_adt()?).into();
197 let edition = module.krate(db).edition(db);
198
199 let ty_path = module.find_path(db, item_for_path_search(db, item_in_ns)?, cfg)?;
200
201 use_trivial_constructor_with_factory(
202 &make,
203 db,
204 mod_path_to_ast_with_factory(&make, &ty_path, edition),
205 &ty,
206 edition,
207 )
208 })
209 .collect()
210}
211
212fn get_fields(strukt: &ast::Struct) -> Option<(Option<Vec<ast::Name>>, Vec<ast::Type>)> {
213 Some(match strukt.kind() {
214 ast::StructKind::Unit => return None,
215 ast::StructKind::Record(fields) => {
216 let names = fields.fields().map(|field| field.name()).collect::<Option<_>>()?;
217 let types = fields.fields().map(|field| field.ty()).collect::<Option<_>>()?;
218 (Some(names), types)
219 }
220 ast::StructKind::Tuple(fields) => {
221 (None, fields.fields().map(|field| field.ty()).collect::<Option<_>>()?)
222 }
223 })
224}
225
226#[tracing::instrument(ret)]
227fn from_impl_exists(
228 strukt: &ast::Struct,
229 main_field_i: usize,
230 sema: &Semantics<'_, RootDatabase>,
231) -> Option<()> {
232 let db = sema.db;
233 let strukt = sema.to_def(strukt)?;
234 let krate = strukt.krate(db);
235 let from_trait = FamousDefs(sema, krate).core_convert_From()?;
236 let interner = DbInterner::new_with(db, krate.base());
237 use hir::next_solver::infer::DbInternerInferExt;
238 let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
239
240 let strukt = strukt.instantiate_infer(&infcx);
241 let field_ty = strukt.fields(db).get(main_field_i)?.ty(db);
242 let struct_ty = strukt.ty(db);
243 tracing::debug!(?strukt, ?field_ty, ?struct_ty);
244 struct_ty.impls_trait(infcx, from_trait, &[field_ty]).then_some(())
245}
246
247#[cfg(test)]
248mod tests {
249 use crate::tests::{check_assist, check_assist_not_applicable};
250
251 use super::generate_single_field_struct_from;
252
253 #[test]
254 fn works() {
255 check_assist(
256 generate_single_field_struct_from,
257 r#"
258 //- minicore: from
259 struct $0Foo {
260 foo: i32,
261 }
262 "#,
263 r#"
264 struct Foo {
265 foo: i32,
266 }
267
268 impl From<i32> for Foo {
269 fn from(foo: i32) -> Self {
270 Self { foo }
271 }
272 }
273 "#,
274 );
275 check_assist(
276 generate_single_field_struct_from,
277 r#"
278 //- minicore: from, phantom_data
279 struct $0Foo {
280 b1: (),
281 b2: core::marker::PhantomData,
282 foo: i32,
283 a1: (),
284 a2: core::marker::PhantomData,
285 }
286 "#,
287 r#"
288 struct Foo {
289 b1: (),
290 b2: core::marker::PhantomData,
291 foo: i32,
292 a1: (),
293 a2: core::marker::PhantomData,
294 }
295
296 impl From<i32> for Foo {
297 fn from(foo: i32) -> Self {
298 Self { b1: (), b2: core::marker::PhantomData, foo, a1: (), a2: core::marker::PhantomData }
299 }
300 }
301 "#,
302 );
303 }
304
305 #[test]
306 fn cfgs() {
307 check_assist(
308 generate_single_field_struct_from,
309 r#"
310 //- minicore: from
311 #[cfg(feature = "foo")]
312 #[cfg(test)]
313 struct $0Foo {
314 foo: i32,
315 }
316 "#,
317 r#"
318 #[cfg(feature = "foo")]
319 #[cfg(test)]
320 struct Foo {
321 foo: i32,
322 }
323
324 #[cfg(feature = "foo")]
325 #[cfg(test)]
326 impl From<i32> for Foo {
327 fn from(foo: i32) -> Self {
328 Self { foo }
329 }
330 }
331 "#,
332 );
333 }
334
335 #[test]
336 fn indent() {
337 check_assist(
338 generate_single_field_struct_from,
339 r#"
340 //- minicore: from
341 mod foo {
342 struct $0Foo {
343 foo: i32,
344 }
345 }
346 "#,
347 r#"
348 mod foo {
349 struct Foo {
350 foo: i32,
351 }
352
353 impl From<i32> for Foo {
354 fn from(foo: i32) -> Self {
355 Self { foo }
356 }
357 }
358 }
359 "#,
360 );
361 check_assist(
362 generate_single_field_struct_from,
363 r#"
364 //- minicore: from
365 mod foo {
366 mod bar {
367 struct $0Foo {
368 foo: i32,
369 }
370 }
371 }
372 "#,
373 r#"
374 mod foo {
375 mod bar {
376 struct Foo {
377 foo: i32,
378 }
379
380 impl From<i32> for Foo {
381 fn from(foo: i32) -> Self {
382 Self { foo }
383 }
384 }
385 }
386 }
387 "#,
388 );
389 }
390
391 #[test]
392 fn where_clause_indent() {
393 check_assist(
394 generate_single_field_struct_from,
395 r#"
396 //- minicore: from
397 mod foo {
398 mod bar {
399 trait Trait {}
400 struct $0Foo<T>
401 where
402 T: Trait,
403 {
404 foo: T,
405 }
406 }
407 }
408 "#,
409 r#"
410 mod foo {
411 mod bar {
412 trait Trait {}
413 struct Foo<T>
414 where
415 T: Trait,
416 {
417 foo: T,
418 }
419
420 impl<T> From<T> for Foo<T>
421 where
422 T: Trait,
423 {
424 fn from(foo: T) -> Self {
425 Self { foo }
426 }
427 }
428 }
429 }
430 "#,
431 );
432 check_assist(
433 generate_single_field_struct_from,
434 r#"
435 //- minicore: from
436 mod foo {
437 mod bar {
438 trait Trait<const B: bool> {}
439 struct $0Foo<T>
440 where
441 T: Trait<{
442 true
443 }>
444 {
445 foo: T,
446 }
447 }
448 }
449 "#,
450 r#"
451 mod foo {
452 mod bar {
453 trait Trait<const B: bool> {}
454 struct Foo<T>
455 where
456 T: Trait<{
457 true
458 }>
459 {
460 foo: T,
461 }
462
463 impl<T> From<T> for Foo<T>
464 where
465 T: Trait<{
466 true
467 }>
468 {
469 fn from(foo: T) -> Self {
470 Self { foo }
471 }
472 }
473 }
474 }
475 "#,
476 );
477 }
478
479 #[test]
480 fn generics() {
481 check_assist(
482 generate_single_field_struct_from,
483 r#"
484 //- minicore: from
485 struct $0Foo<T> {
486 foo: T,
487 }
488 "#,
489 r#"
490 struct Foo<T> {
491 foo: T,
492 }
493
494 impl<T> From<T> for Foo<T> {
495 fn from(foo: T) -> Self {
496 Self { foo }
497 }
498 }
499 "#,
500 );
501 check_assist(
502 generate_single_field_struct_from,
503 r#"
504 //- minicore: from
505 struct $0Foo<T: Send> {
506 foo: T,
507 }
508 "#,
509 r#"
510 struct Foo<T: Send> {
511 foo: T,
512 }
513
514 impl<T: Send> From<T> for Foo<T> {
515 fn from(foo: T) -> Self {
516 Self { foo }
517 }
518 }
519 "#,
520 );
521 check_assist(
522 generate_single_field_struct_from,
523 r#"
524 //- minicore: from
525 struct $0Foo<T: Send> where T: Sync,{
526 foo: T,
527 }
528 "#,
529 r#"
530 struct Foo<T: Send> where T: Sync,{
531 foo: T,
532 }
533
534 impl<T: Send> From<T> for Foo<T>
535 where T: Sync,
536 {
537 fn from(foo: T) -> Self {
538 Self { foo }
539 }
540 }
541 "#,
542 );
543 check_assist(
544 generate_single_field_struct_from,
545 r#"
546 //- minicore: from
547 struct $0Foo<T: Send> where T: Sync {
548 foo: T,
549 }
550 "#,
551 r#"
552 struct Foo<T: Send> where T: Sync {
553 foo: T,
554 }
555
556 impl<T: Send> From<T> for Foo<T>
557 where T: Sync
558 {
559 fn from(foo: T) -> Self {
560 Self { foo }
561 }
562 }
563 "#,
564 );
565 check_assist(
566 generate_single_field_struct_from,
567 r#"
568 //- minicore: from
569 struct $0Foo<T: Send> where T: Sync, Self: Send {
570 foo: T,
571 }
572 "#,
573 r#"
574 struct Foo<T: Send> where T: Sync, Self: Send {
575 foo: T,
576 }
577
578 impl<T: Send> From<T> for Foo<T>
579 where T: Sync, Self: Send
580 {
581 fn from(foo: T) -> Self {
582 Self { foo }
583 }
584 }
585 "#,
586 );
587 check_assist(
588 generate_single_field_struct_from,
589 r#"
590 //- minicore: from
591 struct $0Foo<T: Send>
592 where T: Sync, Self: Send
593 {
594 foo: T,
595 }
596 "#,
597 r#"
598 struct Foo<T: Send>
599 where T: Sync, Self: Send
600 {
601 foo: T,
602 }
603
604 impl<T: Send> From<T> for Foo<T>
605 where T: Sync, Self: Send
606 {
607 fn from(foo: T) -> Self {
608 Self { foo }
609 }
610 }
611 "#,
612 );
613 check_assist(
614 generate_single_field_struct_from,
615 r#"
616 //- minicore: from
617 struct $0Foo<T: Send>
618 where T: Sync, Self: Send,
619 {
620 foo: T,
621 }
622 "#,
623 r#"
624 struct Foo<T: Send>
625 where T: Sync, Self: Send,
626 {
627 foo: T,
628 }
629
630 impl<T: Send> From<T> for Foo<T>
631 where T: Sync, Self: Send,
632 {
633 fn from(foo: T) -> Self {
634 Self { foo }
635 }
636 }
637 "#,
638 );
639 check_assist(
640 generate_single_field_struct_from,
641 r#"
642 //- minicore: from
643 struct $0Foo<T: Send>
644 where T: Sync,
645 Self: Send,
646 {
647 foo: T,
648 }
649 "#,
650 r#"
651 struct Foo<T: Send>
652 where T: Sync,
653 Self: Send,
654 {
655 foo: T,
656 }
657
658 impl<T: Send> From<T> for Foo<T>
659 where T: Sync,
660 Self: Send,
661 {
662 fn from(foo: T) -> Self {
663 Self { foo }
664 }
665 }
666 "#,
667 );
668 check_assist(
669 generate_single_field_struct_from,
670 r#"
671 //- minicore: from
672 struct $0Foo<T: Send>
673 where
674 T: Sync,
675 Self: Send,
676 {
677 foo: T,
678 }
679 "#,
680 r#"
681 struct Foo<T: Send>
682 where
683 T: Sync,
684 Self: Send,
685 {
686 foo: T,
687 }
688
689 impl<T: Send> From<T> for Foo<T>
690 where
691 T: Sync,
692 Self: Send,
693 {
694 fn from(foo: T) -> Self {
695 Self { foo }
696 }
697 }
698 "#,
699 );
700 check_assist(
701 generate_single_field_struct_from,
702 r#"
703 //- minicore: from
704 struct $0Foo<T: Send + Sync>
705 where
706 T: Sync,
707 Self: Send,
708 {
709 foo: T,
710 }
711 "#,
712 r#"
713 struct Foo<T: Send + Sync>
714 where
715 T: Sync,
716 Self: Send,
717 {
718 foo: T,
719 }
720
721 impl<T: Send + Sync> From<T> for Foo<T>
722 where
723 T: Sync,
724 Self: Send,
725 {
726 fn from(foo: T) -> Self {
727 Self { foo }
728 }
729 }
730 "#,
731 );
732 }
733
734 #[test]
735 fn tuple() {
736 check_assist(
737 generate_single_field_struct_from,
738 r#"
739 //- minicore: from
740 struct $0Foo(i32);
741 "#,
742 r#"
743 struct Foo(i32);
744
745 impl From<i32> for Foo {
746 fn from(value: i32) -> Self {
747 Self(value)
748 }
749 }
750 "#,
751 );
752 check_assist(
753 generate_single_field_struct_from,
754 r#"
755 //- minicore: from
756 struct $0Foo<T>(T);
757 "#,
758 r#"
759 struct Foo<T>(T);
760
761 impl<T> From<T> for Foo<T> {
762 fn from(value: T) -> Self {
763 Self(value)
764 }
765 }
766 "#,
767 );
768 }
769
770 #[test]
771 fn trivial() {
772 check_assist(
773 generate_single_field_struct_from,
774 r#"
775 //- minicore: from, phantom_data
776 use core::marker::PhantomData;
777 struct $0Foo(i32, PhantomData<i32>);
778 "#,
779 r#"
780 use core::marker::PhantomData;
781 struct Foo(i32, PhantomData<i32>);
782
783 impl From<i32> for Foo {
784 fn from(value: i32) -> Self {
785 Self(value, PhantomData)
786 }
787 }
788 "#,
789 );
790 check_assist(
791 generate_single_field_struct_from,
792 r#"
793 //- minicore: from, phantom_data
794 use core::marker::PhantomData;
795 struct $0Foo(i32, PhantomData<()>);
796 "#,
797 r#"
798 use core::marker::PhantomData;
799 struct Foo(i32, PhantomData<()>);
800
801 impl From<i32> for Foo {
802 fn from(value: i32) -> Self {
803 Self(value, PhantomData)
804 }
805 }
806 "#,
807 );
808 check_assist(
809 generate_single_field_struct_from,
810 r#"
811 //- minicore: from, phantom_data
812 use core::marker::PhantomData;
813 struct $0Foo(PhantomData<()>, i32, PhantomData<()>);
814 "#,
815 r#"
816 use core::marker::PhantomData;
817 struct Foo(PhantomData<()>, i32, PhantomData<()>);
818
819 impl From<i32> for Foo {
820 fn from(value: i32) -> Self {
821 Self(PhantomData, value, PhantomData)
822 }
823 }
824 "#,
825 );
826 check_assist(
827 generate_single_field_struct_from,
828 r#"
829 //- minicore: from, phantom_data
830 use core::marker::PhantomData;
831 struct $0Foo<T>(PhantomData<T>, i32, PhantomData<()>);
832 "#,
833 r#"
834 use core::marker::PhantomData;
835 struct Foo<T>(PhantomData<T>, i32, PhantomData<()>);
836
837 impl<T> From<i32> for Foo<T> {
838 fn from(value: i32) -> Self {
839 Self(PhantomData, value, PhantomData)
840 }
841 }
842 "#,
843 );
844 }
845
846 #[test]
847 fn unit() {
848 check_assist(
849 generate_single_field_struct_from,
850 r#"
851 //- minicore: from
852 struct $0Foo(i32, ());
853 "#,
854 r#"
855 struct Foo(i32, ());
856
857 impl From<i32> for Foo {
858 fn from(value: i32) -> Self {
859 Self(value, ())
860 }
861 }
862 "#,
863 );
864 check_assist(
865 generate_single_field_struct_from,
866 r#"
867 //- minicore: from
868 struct $0Foo((), i32, ());
869 "#,
870 r#"
871 struct Foo((), i32, ());
872
873 impl From<i32> for Foo {
874 fn from(value: i32) -> Self {
875 Self((), value, ())
876 }
877 }
878 "#,
879 );
880 check_assist(
881 generate_single_field_struct_from,
882 r#"
883 //- minicore: from
884 struct $0Foo((), (), i32, ());
885 "#,
886 r#"
887 struct Foo((), (), i32, ());
888
889 impl From<i32> for Foo {
890 fn from(value: i32) -> Self {
891 Self((), (), value, ())
892 }
893 }
894 "#,
895 );
896 }
897
898 #[test]
899 fn invalid_multiple_main_field() {
900 check_assist_not_applicable(
901 generate_single_field_struct_from,
902 r#"
903 //- minicore: from
904 struct $0Foo(i32, i32);
905 "#,
906 );
907 check_assist_not_applicable(
908 generate_single_field_struct_from,
909 r#"
910 //- minicore: from
911 struct $0Foo<T>(i32, T);
912 "#,
913 );
914 check_assist_not_applicable(
915 generate_single_field_struct_from,
916 r#"
917 //- minicore: from
918 struct $0Foo<T>(T, T);
919 "#,
920 );
921 check_assist_not_applicable(
922 generate_single_field_struct_from,
923 r#"
924 //- minicore: from
925 struct $0Foo<T> { foo: T, bar: i32 }
926 "#,
927 );
928 check_assist_not_applicable(
929 generate_single_field_struct_from,
930 r#"
931 //- minicore: from
932 struct $0Foo { foo: i32, bar: i64 }
933 "#,
934 );
935 }
936
937 #[test]
938 fn exists_other_from() {
939 check_assist(
940 generate_single_field_struct_from,
941 r#"
942 //- minicore: from
943 struct $0Foo(i32);
944
945 impl From<&i32> for Foo {
946 fn from(value: &i32) -> Self {
947 todo!()
948 }
949 }
950 "#,
951 r#"
952 struct Foo(i32);
953
954 impl From<i32> for Foo {
955 fn from(value: i32) -> Self {
956 Self(value)
957 }
958 }
959
960 impl From<&i32> for Foo {
961 fn from(value: &i32) -> Self {
962 todo!()
963 }
964 }
965 "#,
966 );
967 check_assist(
968 generate_single_field_struct_from,
969 r#"
970 //- minicore: from
971 struct $0Foo(i32);
972
973 type X = i32;
974
975 impl From<&X> for Foo {
976 fn from(value: &X) -> Self {
977 todo!()
978 }
979 }
980 "#,
981 r#"
982 struct Foo(i32);
983
984 impl From<i32> for Foo {
985 fn from(value: i32) -> Self {
986 Self(value)
987 }
988 }
989
990 type X = i32;
991
992 impl From<&X> for Foo {
993 fn from(value: &X) -> Self {
994 todo!()
995 }
996 }
997 "#,
998 );
999 }
1000
1001 #[test]
1002 fn exists_from() {
1003 check_assist_not_applicable(
1004 generate_single_field_struct_from,
1005 r#"
1006 //- minicore: from
1007 struct $0Foo(i32);
1008
1009 impl From<i32> for Foo {
1010 fn from(_: i32) -> Self {
1011 todo!()
1012 }
1013 }
1014 "#,
1015 );
1016 check_assist_not_applicable(
1017 generate_single_field_struct_from,
1018 r#"
1019 //- minicore: from
1020 struct $0Foo(i32);
1021
1022 type X = i32;
1023
1024 impl From<X> for Foo {
1025 fn from(_: X) -> Self {
1026 todo!()
1027 }
1028 }
1029 "#,
1030 );
1031 }
1032}