]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
:arrow_up: rust-analyzer
[rust.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / generate_function.rs
1 use hir::{Adt, HasSource, HirDisplay, Module, Semantics, TypeInfo};
2 use ide_db::{
3     base_db::FileId,
4     defs::{Definition, NameRefClass},
5     famous_defs::FamousDefs,
6     FxHashMap, FxHashSet, RootDatabase, SnippetCap,
7 };
8 use stdx::to_lower_snake_case;
9 use syntax::{
10     ast::{
11         self,
12         edit::{AstNodeEdit, IndentLevel},
13         make, AstNode, CallExpr, HasArgList, HasModuleItem,
14     },
15     SyntaxKind, SyntaxNode, TextRange, TextSize,
16 };
17
18 use crate::{
19     utils::convert_reference_type,
20     utils::{find_struct_impl, render_snippet, Cursor},
21     AssistContext, AssistId, AssistKind, Assists,
22 };
23
24 // Assist: generate_function
25 //
26 // Adds a stub function with a signature matching the function under the cursor.
27 //
28 // ```
29 // struct Baz;
30 // fn baz() -> Baz { Baz }
31 // fn foo() {
32 //     bar$0("", baz());
33 // }
34 //
35 // ```
36 // ->
37 // ```
38 // struct Baz;
39 // fn baz() -> Baz { Baz }
40 // fn foo() {
41 //     bar("", baz());
42 // }
43 //
44 // fn bar(arg: &str, baz: Baz) ${0:-> _} {
45 //     todo!()
46 // }
47 //
48 // ```
49 pub(crate) fn generate_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
50     gen_fn(acc, ctx).or_else(|| gen_method(acc, ctx))
51 }
52
53 fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
54     let path_expr: ast::PathExpr = ctx.find_node_at_offset()?;
55     let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?;
56     let path = path_expr.path()?;
57     let name_ref = path.segment()?.name_ref()?;
58     if ctx.sema.resolve_path(&path).is_some() {
59         // The function call already resolves, no need to add a function
60         return None;
61     }
62
63     let fn_name = &*name_ref.text();
64     let TargetInfo { target_module, adt_name, target, file, insert_offset } =
65         fn_target_info(ctx, path, &call, fn_name)?;
66     let function_builder = FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target)?;
67     let text_range = call.syntax().text_range();
68     let label = format!("Generate {} function", function_builder.fn_name);
69     add_func_to_accumulator(
70         acc,
71         ctx,
72         text_range,
73         function_builder,
74         insert_offset,
75         file,
76         adt_name,
77         label,
78     )
79 }
80
81 struct TargetInfo {
82     target_module: Option<Module>,
83     adt_name: Option<hir::Name>,
84     target: GeneratedFunctionTarget,
85     file: FileId,
86     insert_offset: TextSize,
87 }
88
89 impl TargetInfo {
90     fn new(
91         target_module: Option<Module>,
92         adt_name: Option<hir::Name>,
93         target: GeneratedFunctionTarget,
94         file: FileId,
95         insert_offset: TextSize,
96     ) -> Self {
97         Self { target_module, adt_name, target, file, insert_offset }
98     }
99 }
100
101 fn fn_target_info(
102     ctx: &AssistContext<'_>,
103     path: ast::Path,
104     call: &CallExpr,
105     fn_name: &str,
106 ) -> Option<TargetInfo> {
107     match path.qualifier() {
108         Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
109             Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => {
110                 get_fn_target_info(ctx, &Some(module), call.clone())
111             }
112             Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
113                 if let hir::Adt::Enum(_) = adt {
114                     // Don't suggest generating function if the name starts with an uppercase letter
115                     if fn_name.starts_with(char::is_uppercase) {
116                         return None;
117                     }
118                 }
119
120                 assoc_fn_target_info(ctx, call, adt, fn_name)
121             }
122             Some(hir::PathResolution::SelfType(impl_)) => {
123                 let adt = impl_.self_ty(ctx.db()).as_adt()?;
124                 assoc_fn_target_info(ctx, call, adt, fn_name)
125             }
126             _ => None,
127         },
128         _ => get_fn_target_info(ctx, &None, call.clone()),
129     }
130 }
131
132 fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
133     let call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
134     if ctx.sema.resolve_method_call(&call).is_some() {
135         return None;
136     }
137
138     let fn_name = call.name_ref()?;
139     let adt = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references().as_adt()?;
140
141     let current_module = ctx.sema.scope(call.syntax())?.module();
142     let target_module = adt.module(ctx.sema.db);
143
144     if current_module.krate() != target_module.krate() {
145         return None;
146     }
147     let (impl_, file) = get_adt_source(ctx, &adt, fn_name.text().as_str())?;
148     let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
149
150     let function_builder =
151         FunctionBuilder::from_method_call(ctx, &call, &fn_name, target_module, target)?;
152     let text_range = call.syntax().text_range();
153     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
154     let label = format!("Generate {} method", function_builder.fn_name);
155     add_func_to_accumulator(
156         acc,
157         ctx,
158         text_range,
159         function_builder,
160         insert_offset,
161         file,
162         adt_name,
163         label,
164     )
165 }
166
167 fn add_func_to_accumulator(
168     acc: &mut Assists,
169     ctx: &AssistContext<'_>,
170     text_range: TextRange,
171     function_builder: FunctionBuilder,
172     insert_offset: TextSize,
173     file: FileId,
174     adt_name: Option<hir::Name>,
175     label: String,
176 ) -> Option<()> {
177     acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |builder| {
178         let indent = IndentLevel::from_node(function_builder.target.syntax());
179         let function_template = function_builder.render(adt_name.is_some());
180         let mut func = function_template.to_string(ctx.config.snippet_cap);
181         if let Some(name) = adt_name {
182             func = format!("\n{}impl {} {{\n{}\n{}}}", indent, name, func, indent);
183         }
184         builder.edit_file(file);
185         match ctx.config.snippet_cap {
186             Some(cap) => builder.insert_snippet(cap, insert_offset, func),
187             None => builder.insert(insert_offset, func),
188         }
189     })
190 }
191
192 fn get_adt_source(
193     ctx: &AssistContext<'_>,
194     adt: &hir::Adt,
195     fn_name: &str,
196 ) -> Option<(Option<ast::Impl>, FileId)> {
197     let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db);
198     let file = ctx.sema.parse(range.file_id);
199     let adt_source =
200         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
201     find_struct_impl(ctx, &adt_source, fn_name).map(|impl_| (impl_, range.file_id))
202 }
203
204 struct FunctionTemplate {
205     leading_ws: String,
206     fn_def: ast::Fn,
207     ret_type: Option<ast::RetType>,
208     should_focus_return_type: bool,
209     trailing_ws: String,
210     tail_expr: ast::Expr,
211 }
212
213 impl FunctionTemplate {
214     fn to_string(&self, cap: Option<SnippetCap>) -> String {
215         let f = match cap {
216             Some(cap) => {
217                 let cursor = if self.should_focus_return_type {
218                     // Focus the return type if there is one
219                     match self.ret_type {
220                         Some(ref ret_type) => ret_type.syntax(),
221                         None => self.tail_expr.syntax(),
222                     }
223                 } else {
224                     self.tail_expr.syntax()
225                 };
226                 render_snippet(cap, self.fn_def.syntax(), Cursor::Replace(cursor))
227             }
228             None => self.fn_def.to_string(),
229         };
230
231         format!("{}{}{}", self.leading_ws, f, self.trailing_ws)
232     }
233 }
234
235 struct FunctionBuilder {
236     target: GeneratedFunctionTarget,
237     fn_name: ast::Name,
238     type_params: Option<ast::GenericParamList>,
239     params: ast::ParamList,
240     ret_type: Option<ast::RetType>,
241     should_focus_return_type: bool,
242     needs_pub: bool,
243     is_async: bool,
244 }
245
246 impl FunctionBuilder {
247     /// Prepares a generated function that matches `call`.
248     /// The function is generated in `target_module` or next to `call`
249     fn from_call(
250         ctx: &AssistContext<'_>,
251         call: &ast::CallExpr,
252         fn_name: &str,
253         target_module: Option<hir::Module>,
254         target: GeneratedFunctionTarget,
255     ) -> Option<Self> {
256         let needs_pub = target_module.is_some();
257         let target_module =
258             target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
259         let fn_name = make::name(fn_name);
260         let (type_params, params) =
261             fn_args(ctx, target_module, ast::CallableExpr::Call(call.clone()))?;
262
263         let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
264         let is_async = await_expr.is_some();
265
266         let (ret_type, should_focus_return_type) =
267             make_return_type(ctx, &ast::Expr::CallExpr(call.clone()), target_module);
268
269         Some(Self {
270             target,
271             fn_name,
272             type_params,
273             params,
274             ret_type,
275             should_focus_return_type,
276             needs_pub,
277             is_async,
278         })
279     }
280
281     fn from_method_call(
282         ctx: &AssistContext<'_>,
283         call: &ast::MethodCallExpr,
284         name: &ast::NameRef,
285         target_module: Module,
286         target: GeneratedFunctionTarget,
287     ) -> Option<Self> {
288         let needs_pub =
289             !module_is_descendant(&ctx.sema.scope(call.syntax())?.module(), &target_module, ctx);
290         let fn_name = make::name(&name.text());
291         let (type_params, params) =
292             fn_args(ctx, target_module, ast::CallableExpr::MethodCall(call.clone()))?;
293
294         let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
295         let is_async = await_expr.is_some();
296
297         let (ret_type, should_focus_return_type) =
298             make_return_type(ctx, &ast::Expr::MethodCallExpr(call.clone()), target_module);
299
300         Some(Self {
301             target,
302             fn_name,
303             type_params,
304             params,
305             ret_type,
306             should_focus_return_type,
307             needs_pub,
308             is_async,
309         })
310     }
311
312     fn render(self, is_method: bool) -> FunctionTemplate {
313         let placeholder_expr = make::ext::expr_todo();
314         let fn_body = make::block_expr(vec![], Some(placeholder_expr));
315         let visibility = if self.needs_pub { Some(make::visibility_pub_crate()) } else { None };
316         let mut fn_def = make::fn_(
317             visibility,
318             self.fn_name,
319             self.type_params,
320             self.params,
321             fn_body,
322             self.ret_type,
323             self.is_async,
324         );
325         let leading_ws;
326         let trailing_ws;
327
328         match self.target {
329             GeneratedFunctionTarget::BehindItem(it) => {
330                 let mut indent = IndentLevel::from_node(&it);
331                 if is_method {
332                     indent = indent + 1;
333                     leading_ws = format!("{}", indent);
334                 } else {
335                     leading_ws = format!("\n\n{}", indent);
336                 }
337
338                 fn_def = fn_def.indent(indent);
339                 trailing_ws = String::new();
340             }
341             GeneratedFunctionTarget::InEmptyItemList(it) => {
342                 let indent = IndentLevel::from_node(&it);
343                 leading_ws = format!("\n{}", indent + 1);
344                 fn_def = fn_def.indent(indent + 1);
345                 trailing_ws = format!("\n{}", indent);
346             }
347         };
348
349         FunctionTemplate {
350             leading_ws,
351             ret_type: fn_def.ret_type(),
352             // PANIC: we guarantee we always create a function body with a tail expr
353             tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
354             should_focus_return_type: self.should_focus_return_type,
355             fn_def,
356             trailing_ws,
357         }
358     }
359 }
360
361 /// Makes an optional return type along with whether the return type should be focused by the cursor.
362 /// If we cannot infer what the return type should be, we create a placeholder type.
363 ///
364 /// The rule for whether we focus a return type or not (and thus focus the function body),
365 /// is rather simple:
366 /// * If we could *not* infer what the return type should be, focus it (so the user can fill-in
367 /// the correct return type).
368 /// * If we could infer the return type, don't focus it (and thus focus the function body) so the
369 /// user can change the `todo!` function body.
370 fn make_return_type(
371     ctx: &AssistContext<'_>,
372     call: &ast::Expr,
373     target_module: Module,
374 ) -> (Option<ast::RetType>, bool) {
375     let (ret_ty, should_focus_return_type) = {
376         match ctx.sema.type_of_expr(call).map(TypeInfo::original) {
377             Some(ty) if ty.is_unknown() => (Some(make::ty_placeholder()), true),
378             None => (Some(make::ty_placeholder()), true),
379             Some(ty) if ty.is_unit() => (None, false),
380             Some(ty) => {
381                 let rendered = ty.display_source_code(ctx.db(), target_module.into());
382                 match rendered {
383                     Ok(rendered) => (Some(make::ty(&rendered)), false),
384                     Err(_) => (Some(make::ty_placeholder()), true),
385                 }
386             }
387         }
388     };
389     let ret_type = ret_ty.map(make::ret_type);
390     (ret_type, should_focus_return_type)
391 }
392
393 fn get_fn_target_info(
394     ctx: &AssistContext<'_>,
395     target_module: &Option<Module>,
396     call: CallExpr,
397 ) -> Option<TargetInfo> {
398     let (target, file, insert_offset) = get_fn_target(ctx, target_module, call)?;
399     Some(TargetInfo::new(*target_module, None, target, file, insert_offset))
400 }
401
402 fn get_fn_target(
403     ctx: &AssistContext<'_>,
404     target_module: &Option<Module>,
405     call: CallExpr,
406 ) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> {
407     let mut file = ctx.file_id();
408     let target = match target_module {
409         Some(target_module) => {
410             let module_source = target_module.definition_source(ctx.db());
411             let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
412             file = in_file;
413             target
414         }
415         None => next_space_for_fn_after_call_site(ast::CallableExpr::Call(call))?,
416     };
417     Some((target.clone(), file, get_insert_offset(&target)))
418 }
419
420 fn get_method_target(
421     ctx: &AssistContext<'_>,
422     impl_: &Option<ast::Impl>,
423     adt: &Adt,
424 ) -> Option<(GeneratedFunctionTarget, TextSize)> {
425     let target = match impl_ {
426         Some(impl_) => next_space_for_fn_in_impl(impl_)?,
427         None => {
428             GeneratedFunctionTarget::BehindItem(adt.source(ctx.sema.db)?.syntax().value.clone())
429         }
430     };
431     Some((target.clone(), get_insert_offset(&target)))
432 }
433
434 fn assoc_fn_target_info(
435     ctx: &AssistContext<'_>,
436     call: &CallExpr,
437     adt: hir::Adt,
438     fn_name: &str,
439 ) -> Option<TargetInfo> {
440     let current_module = ctx.sema.scope(call.syntax())?.module();
441     let module = adt.module(ctx.sema.db);
442     let target_module = if current_module == module { None } else { Some(module) };
443     if current_module.krate() != module.krate() {
444         return None;
445     }
446     let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
447     let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
448     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
449     Some(TargetInfo::new(target_module, adt_name, target, file, insert_offset))
450 }
451
452 fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize {
453     match &target {
454         GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
455         GeneratedFunctionTarget::InEmptyItemList(it) => it.text_range().start() + TextSize::of('{'),
456     }
457 }
458
459 #[derive(Clone)]
460 enum GeneratedFunctionTarget {
461     BehindItem(SyntaxNode),
462     InEmptyItemList(SyntaxNode),
463 }
464
465 impl GeneratedFunctionTarget {
466     fn syntax(&self) -> &SyntaxNode {
467         match self {
468             GeneratedFunctionTarget::BehindItem(it) => it,
469             GeneratedFunctionTarget::InEmptyItemList(it) => it,
470         }
471     }
472 }
473
474 /// Computes the type variables and arguments required for the generated function
475 fn fn_args(
476     ctx: &AssistContext<'_>,
477     target_module: hir::Module,
478     call: ast::CallableExpr,
479 ) -> Option<(Option<ast::GenericParamList>, ast::ParamList)> {
480     let mut arg_names = Vec::new();
481     let mut arg_types = Vec::new();
482     for arg in call.arg_list()?.args() {
483         arg_names.push(fn_arg_name(&ctx.sema, &arg));
484         arg_types.push(fn_arg_type(ctx, target_module, &arg));
485     }
486     deduplicate_arg_names(&mut arg_names);
487     let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| {
488         make::param(make::ext::simple_ident_pat(make::name(&name)).into(), make::ty(&ty))
489     });
490
491     Some((
492         None,
493         make::param_list(
494             match call {
495                 ast::CallableExpr::Call(_) => None,
496                 ast::CallableExpr::MethodCall(_) => Some(make::self_param()),
497             },
498             params,
499         ),
500     ))
501 }
502
503 /// Makes duplicate argument names unique by appending incrementing numbers.
504 ///
505 /// ```
506 /// let mut names: Vec<String> =
507 ///     vec!["foo".into(), "foo".into(), "bar".into(), "baz".into(), "bar".into()];
508 /// deduplicate_arg_names(&mut names);
509 /// let expected: Vec<String> =
510 ///     vec!["foo_1".into(), "foo_2".into(), "bar_1".into(), "baz".into(), "bar_2".into()];
511 /// assert_eq!(names, expected);
512 /// ```
513 fn deduplicate_arg_names(arg_names: &mut Vec<String>) {
514     let mut arg_name_counts = FxHashMap::default();
515     for name in arg_names.iter() {
516         *arg_name_counts.entry(name).or_insert(0) += 1;
517     }
518     let duplicate_arg_names: FxHashSet<String> = arg_name_counts
519         .into_iter()
520         .filter(|(_, count)| *count >= 2)
521         .map(|(name, _)| name.clone())
522         .collect();
523
524     let mut counter_per_name = FxHashMap::default();
525     for arg_name in arg_names.iter_mut() {
526         if duplicate_arg_names.contains(arg_name) {
527             let counter = counter_per_name.entry(arg_name.clone()).or_insert(1);
528             arg_name.push('_');
529             arg_name.push_str(&counter.to_string());
530             *counter += 1;
531         }
532     }
533 }
534
535 fn fn_arg_name(sema: &Semantics<'_, RootDatabase>, arg_expr: &ast::Expr) -> String {
536     let name = (|| match arg_expr {
537         ast::Expr::CastExpr(cast_expr) => Some(fn_arg_name(sema, &cast_expr.expr()?)),
538         expr => {
539             let name_ref = expr
540                 .syntax()
541                 .descendants()
542                 .filter_map(ast::NameRef::cast)
543                 .filter(|name| name.ident_token().is_some())
544                 .last()?;
545             if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_))) =
546                 NameRefClass::classify(sema, &name_ref)
547             {
548                 return Some(name_ref.to_string().to_lowercase());
549             };
550             Some(to_lower_snake_case(&name_ref.to_string()))
551         }
552     })();
553     match name {
554         Some(mut name) if name.starts_with(|c: char| c.is_ascii_digit()) => {
555             name.insert_str(0, "arg");
556             name
557         }
558         Some(name) => name,
559         None => "arg".to_string(),
560     }
561 }
562
563 fn fn_arg_type(ctx: &AssistContext<'_>, target_module: hir::Module, fn_arg: &ast::Expr) -> String {
564     fn maybe_displayed_type(
565         ctx: &AssistContext<'_>,
566         target_module: hir::Module,
567         fn_arg: &ast::Expr,
568     ) -> Option<String> {
569         let ty = ctx.sema.type_of_expr(fn_arg)?.adjusted();
570         if ty.is_unknown() {
571             return None;
572         }
573
574         if ty.is_reference() || ty.is_mutable_reference() {
575             let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
576             convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
577                 .map(|conversion| conversion.convert_type(ctx.db()))
578                 .or_else(|| ty.display_source_code(ctx.db(), target_module.into()).ok())
579         } else {
580             ty.display_source_code(ctx.db(), target_module.into()).ok()
581         }
582     }
583
584     maybe_displayed_type(ctx, target_module, fn_arg).unwrap_or_else(|| String::from("_"))
585 }
586
587 /// Returns the position inside the current mod or file
588 /// directly after the current block
589 /// We want to write the generated function directly after
590 /// fns, impls or macro calls, but inside mods
591 fn next_space_for_fn_after_call_site(expr: ast::CallableExpr) -> Option<GeneratedFunctionTarget> {
592     let mut ancestors = expr.syntax().ancestors().peekable();
593     let mut last_ancestor: Option<SyntaxNode> = None;
594     while let Some(next_ancestor) = ancestors.next() {
595         match next_ancestor.kind() {
596             SyntaxKind::SOURCE_FILE => {
597                 break;
598             }
599             SyntaxKind::ITEM_LIST => {
600                 if ancestors.peek().map(|a| a.kind()) == Some(SyntaxKind::MODULE) {
601                     break;
602                 }
603             }
604             _ => {}
605         }
606         last_ancestor = Some(next_ancestor);
607     }
608     last_ancestor.map(GeneratedFunctionTarget::BehindItem)
609 }
610
611 fn next_space_for_fn_in_module(
612     db: &dyn hir::db::AstDatabase,
613     module_source: &hir::InFile<hir::ModuleSource>,
614 ) -> Option<(FileId, GeneratedFunctionTarget)> {
615     let file = module_source.file_id.original_file(db);
616     let assist_item = match &module_source.value {
617         hir::ModuleSource::SourceFile(it) => match it.items().last() {
618             Some(last_item) => GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()),
619             None => GeneratedFunctionTarget::BehindItem(it.syntax().clone()),
620         },
621         hir::ModuleSource::Module(it) => match it.item_list().and_then(|it| it.items().last()) {
622             Some(last_item) => GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()),
623             None => GeneratedFunctionTarget::InEmptyItemList(it.item_list()?.syntax().clone()),
624         },
625         hir::ModuleSource::BlockExpr(it) => {
626             if let Some(last_item) =
627                 it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last()
628             {
629                 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
630             } else {
631                 GeneratedFunctionTarget::InEmptyItemList(it.syntax().clone())
632             }
633         }
634     };
635     Some((file, assist_item))
636 }
637
638 fn next_space_for_fn_in_impl(impl_: &ast::Impl) -> Option<GeneratedFunctionTarget> {
639     if let Some(last_item) = impl_.assoc_item_list().and_then(|it| it.assoc_items().last()) {
640         Some(GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()))
641     } else {
642         Some(GeneratedFunctionTarget::InEmptyItemList(impl_.assoc_item_list()?.syntax().clone()))
643     }
644 }
645
646 fn module_is_descendant(module: &hir::Module, ans: &hir::Module, ctx: &AssistContext<'_>) -> bool {
647     if module == ans {
648         return true;
649     }
650     for c in ans.children(ctx.sema.db) {
651         if module_is_descendant(module, &c, ctx) {
652             return true;
653         }
654     }
655     false
656 }
657
658 #[cfg(test)]
659 mod tests {
660     use crate::tests::{check_assist, check_assist_not_applicable};
661
662     use super::*;
663
664     #[test]
665     fn add_function_with_no_args() {
666         check_assist(
667             generate_function,
668             r"
669 fn foo() {
670     bar$0();
671 }
672 ",
673             r"
674 fn foo() {
675     bar();
676 }
677
678 fn bar() ${0:-> _} {
679     todo!()
680 }
681 ",
682         )
683     }
684
685     #[test]
686     fn add_function_from_method() {
687         // This ensures that the function is correctly generated
688         // in the next outer mod or file
689         check_assist(
690             generate_function,
691             r"
692 impl Foo {
693     fn foo() {
694         bar$0();
695     }
696 }
697 ",
698             r"
699 impl Foo {
700     fn foo() {
701         bar();
702     }
703 }
704
705 fn bar() ${0:-> _} {
706     todo!()
707 }
708 ",
709         )
710     }
711
712     #[test]
713     fn add_function_directly_after_current_block() {
714         // The new fn should not be created at the end of the file or module
715         check_assist(
716             generate_function,
717             r"
718 fn foo1() {
719     bar$0();
720 }
721
722 fn foo2() {}
723 ",
724             r"
725 fn foo1() {
726     bar();
727 }
728
729 fn bar() ${0:-> _} {
730     todo!()
731 }
732
733 fn foo2() {}
734 ",
735         )
736     }
737
738     #[test]
739     fn add_function_with_no_args_in_same_module() {
740         check_assist(
741             generate_function,
742             r"
743 mod baz {
744     fn foo() {
745         bar$0();
746     }
747 }
748 ",
749             r"
750 mod baz {
751     fn foo() {
752         bar();
753     }
754
755     fn bar() ${0:-> _} {
756         todo!()
757     }
758 }
759 ",
760         )
761     }
762
763     #[test]
764     fn add_function_with_upper_camel_case_arg() {
765         check_assist(
766             generate_function,
767             r"
768 struct BazBaz;
769 fn foo() {
770     bar$0(BazBaz);
771 }
772 ",
773             r"
774 struct BazBaz;
775 fn foo() {
776     bar(BazBaz);
777 }
778
779 fn bar(baz_baz: BazBaz) ${0:-> _} {
780     todo!()
781 }
782 ",
783         );
784     }
785
786     #[test]
787     fn add_function_with_upper_camel_case_arg_as_cast() {
788         check_assist(
789             generate_function,
790             r"
791 struct BazBaz;
792 fn foo() {
793     bar$0(&BazBaz as *const BazBaz);
794 }
795 ",
796             r"
797 struct BazBaz;
798 fn foo() {
799     bar(&BazBaz as *const BazBaz);
800 }
801
802 fn bar(baz_baz: *const BazBaz) ${0:-> _} {
803     todo!()
804 }
805 ",
806         );
807     }
808
809     #[test]
810     fn add_function_with_function_call_arg() {
811         check_assist(
812             generate_function,
813             r"
814 struct Baz;
815 fn baz() -> Baz { todo!() }
816 fn foo() {
817     bar$0(baz());
818 }
819 ",
820             r"
821 struct Baz;
822 fn baz() -> Baz { todo!() }
823 fn foo() {
824     bar(baz());
825 }
826
827 fn bar(baz: Baz) ${0:-> _} {
828     todo!()
829 }
830 ",
831         );
832     }
833
834     #[test]
835     fn add_function_with_method_call_arg() {
836         check_assist(
837             generate_function,
838             r"
839 struct Baz;
840 impl Baz {
841     fn foo(&self) -> Baz {
842         ba$0r(self.baz())
843     }
844     fn baz(&self) -> Baz {
845         Baz
846     }
847 }
848 ",
849             r"
850 struct Baz;
851 impl Baz {
852     fn foo(&self) -> Baz {
853         bar(self.baz())
854     }
855     fn baz(&self) -> Baz {
856         Baz
857     }
858 }
859
860 fn bar(baz: Baz) -> Baz {
861     ${0:todo!()}
862 }
863 ",
864         )
865     }
866
867     #[test]
868     fn add_function_with_string_literal_arg() {
869         check_assist(
870             generate_function,
871             r#"
872 fn foo() {
873     $0bar("bar")
874 }
875 "#,
876             r#"
877 fn foo() {
878     bar("bar")
879 }
880
881 fn bar(arg: &str) {
882     ${0:todo!()}
883 }
884 "#,
885         )
886     }
887
888     #[test]
889     fn add_function_with_char_literal_arg() {
890         check_assist(
891             generate_function,
892             r#"
893 fn foo() {
894     $0bar('x')
895 }
896 "#,
897             r#"
898 fn foo() {
899     bar('x')
900 }
901
902 fn bar(arg: char) {
903     ${0:todo!()}
904 }
905 "#,
906         )
907     }
908
909     #[test]
910     fn add_function_with_int_literal_arg() {
911         check_assist(
912             generate_function,
913             r"
914 fn foo() {
915     $0bar(42)
916 }
917 ",
918             r"
919 fn foo() {
920     bar(42)
921 }
922
923 fn bar(arg: i32) {
924     ${0:todo!()}
925 }
926 ",
927         )
928     }
929
930     #[test]
931     fn add_function_with_cast_int_literal_arg() {
932         check_assist(
933             generate_function,
934             r"
935 fn foo() {
936     $0bar(42 as u8)
937 }
938 ",
939             r"
940 fn foo() {
941     bar(42 as u8)
942 }
943
944 fn bar(arg: u8) {
945     ${0:todo!()}
946 }
947 ",
948         )
949     }
950
951     #[test]
952     fn name_of_cast_variable_is_used() {
953         // Ensures that the name of the cast type isn't used
954         // in the generated function signature.
955         check_assist(
956             generate_function,
957             r"
958 fn foo() {
959     let x = 42;
960     bar$0(x as u8)
961 }
962 ",
963             r"
964 fn foo() {
965     let x = 42;
966     bar(x as u8)
967 }
968
969 fn bar(x: u8) {
970     ${0:todo!()}
971 }
972 ",
973         )
974     }
975
976     #[test]
977     fn add_function_with_variable_arg() {
978         check_assist(
979             generate_function,
980             r"
981 fn foo() {
982     let worble = ();
983     $0bar(worble)
984 }
985 ",
986             r"
987 fn foo() {
988     let worble = ();
989     bar(worble)
990 }
991
992 fn bar(worble: ()) {
993     ${0:todo!()}
994 }
995 ",
996         )
997     }
998
999     #[test]
1000     fn add_function_with_impl_trait_arg() {
1001         check_assist(
1002             generate_function,
1003             r#"
1004 //- minicore: sized
1005 trait Foo {}
1006 fn foo() -> impl Foo {
1007     todo!()
1008 }
1009 fn baz() {
1010     $0bar(foo())
1011 }
1012 "#,
1013             r#"
1014 trait Foo {}
1015 fn foo() -> impl Foo {
1016     todo!()
1017 }
1018 fn baz() {
1019     bar(foo())
1020 }
1021
1022 fn bar(foo: impl Foo) {
1023     ${0:todo!()}
1024 }
1025 "#,
1026         )
1027     }
1028
1029     #[test]
1030     fn borrowed_arg() {
1031         check_assist(
1032             generate_function,
1033             r"
1034 struct Baz;
1035 fn baz() -> Baz { todo!() }
1036
1037 fn foo() {
1038     bar$0(&baz())
1039 }
1040 ",
1041             r"
1042 struct Baz;
1043 fn baz() -> Baz { todo!() }
1044
1045 fn foo() {
1046     bar(&baz())
1047 }
1048
1049 fn bar(baz: &Baz) {
1050     ${0:todo!()}
1051 }
1052 ",
1053         )
1054     }
1055
1056     #[test]
1057     fn add_function_with_qualified_path_arg() {
1058         check_assist(
1059             generate_function,
1060             r"
1061 mod Baz {
1062     pub struct Bof;
1063     pub fn baz() -> Bof { Bof }
1064 }
1065 fn foo() {
1066     $0bar(Baz::baz())
1067 }
1068 ",
1069             r"
1070 mod Baz {
1071     pub struct Bof;
1072     pub fn baz() -> Bof { Bof }
1073 }
1074 fn foo() {
1075     bar(Baz::baz())
1076 }
1077
1078 fn bar(baz: Baz::Bof) {
1079     ${0:todo!()}
1080 }
1081 ",
1082         )
1083     }
1084
1085     #[test]
1086     fn add_function_with_generic_arg() {
1087         // FIXME: This is wrong, generated `bar` should include generic parameter.
1088         check_assist(
1089             generate_function,
1090             r"
1091 fn foo<T>(t: T) {
1092     $0bar(t)
1093 }
1094 ",
1095             r"
1096 fn foo<T>(t: T) {
1097     bar(t)
1098 }
1099
1100 fn bar(t: T) {
1101     ${0:todo!()}
1102 }
1103 ",
1104         )
1105     }
1106
1107     #[test]
1108     fn add_function_with_fn_arg() {
1109         // FIXME: The argument in `bar` is wrong.
1110         check_assist(
1111             generate_function,
1112             r"
1113 struct Baz;
1114 impl Baz {
1115     fn new() -> Self { Baz }
1116 }
1117 fn foo() {
1118     $0bar(Baz::new);
1119 }
1120 ",
1121             r"
1122 struct Baz;
1123 impl Baz {
1124     fn new() -> Self { Baz }
1125 }
1126 fn foo() {
1127     bar(Baz::new);
1128 }
1129
1130 fn bar(new: fn) ${0:-> _} {
1131     todo!()
1132 }
1133 ",
1134         )
1135     }
1136
1137     #[test]
1138     fn add_function_with_closure_arg() {
1139         // FIXME: The argument in `bar` is wrong.
1140         check_assist(
1141             generate_function,
1142             r"
1143 fn foo() {
1144     let closure = |x: i64| x - 1;
1145     $0bar(closure)
1146 }
1147 ",
1148             r"
1149 fn foo() {
1150     let closure = |x: i64| x - 1;
1151     bar(closure)
1152 }
1153
1154 fn bar(closure: _) {
1155     ${0:todo!()}
1156 }
1157 ",
1158         )
1159     }
1160
1161     #[test]
1162     fn unresolveable_types_default_to_placeholder() {
1163         check_assist(
1164             generate_function,
1165             r"
1166 fn foo() {
1167     $0bar(baz)
1168 }
1169 ",
1170             r"
1171 fn foo() {
1172     bar(baz)
1173 }
1174
1175 fn bar(baz: _) {
1176     ${0:todo!()}
1177 }
1178 ",
1179         )
1180     }
1181
1182     #[test]
1183     fn arg_names_dont_overlap() {
1184         check_assist(
1185             generate_function,
1186             r"
1187 struct Baz;
1188 fn baz() -> Baz { Baz }
1189 fn foo() {
1190     $0bar(baz(), baz())
1191 }
1192 ",
1193             r"
1194 struct Baz;
1195 fn baz() -> Baz { Baz }
1196 fn foo() {
1197     bar(baz(), baz())
1198 }
1199
1200 fn bar(baz_1: Baz, baz_2: Baz) {
1201     ${0:todo!()}
1202 }
1203 ",
1204         )
1205     }
1206
1207     #[test]
1208     fn arg_name_counters_start_at_1_per_name() {
1209         check_assist(
1210             generate_function,
1211             r#"
1212 struct Baz;
1213 fn baz() -> Baz { Baz }
1214 fn foo() {
1215     $0bar(baz(), baz(), "foo", "bar")
1216 }
1217 "#,
1218             r#"
1219 struct Baz;
1220 fn baz() -> Baz { Baz }
1221 fn foo() {
1222     bar(baz(), baz(), "foo", "bar")
1223 }
1224
1225 fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
1226     ${0:todo!()}
1227 }
1228 "#,
1229         )
1230     }
1231
1232     #[test]
1233     fn add_function_in_module() {
1234         check_assist(
1235             generate_function,
1236             r"
1237 mod bar {}
1238
1239 fn foo() {
1240     bar::my_fn$0()
1241 }
1242 ",
1243             r"
1244 mod bar {
1245     pub(crate) fn my_fn() {
1246         ${0:todo!()}
1247     }
1248 }
1249
1250 fn foo() {
1251     bar::my_fn()
1252 }
1253 ",
1254         )
1255     }
1256
1257     #[test]
1258     fn qualified_path_uses_correct_scope() {
1259         check_assist(
1260             generate_function,
1261             r#"
1262 mod foo {
1263     pub struct Foo;
1264 }
1265 fn bar() {
1266     use foo::Foo;
1267     let foo = Foo;
1268     baz$0(foo)
1269 }
1270 "#,
1271             r#"
1272 mod foo {
1273     pub struct Foo;
1274 }
1275 fn bar() {
1276     use foo::Foo;
1277     let foo = Foo;
1278     baz(foo)
1279 }
1280
1281 fn baz(foo: foo::Foo) {
1282     ${0:todo!()}
1283 }
1284 "#,
1285         )
1286     }
1287
1288     #[test]
1289     fn add_function_in_module_containing_other_items() {
1290         check_assist(
1291             generate_function,
1292             r"
1293 mod bar {
1294     fn something_else() {}
1295 }
1296
1297 fn foo() {
1298     bar::my_fn$0()
1299 }
1300 ",
1301             r"
1302 mod bar {
1303     fn something_else() {}
1304
1305     pub(crate) fn my_fn() {
1306         ${0:todo!()}
1307     }
1308 }
1309
1310 fn foo() {
1311     bar::my_fn()
1312 }
1313 ",
1314         )
1315     }
1316
1317     #[test]
1318     fn add_function_in_nested_module() {
1319         check_assist(
1320             generate_function,
1321             r"
1322 mod bar {
1323     mod baz {}
1324 }
1325
1326 fn foo() {
1327     bar::baz::my_fn$0()
1328 }
1329 ",
1330             r"
1331 mod bar {
1332     mod baz {
1333         pub(crate) fn my_fn() {
1334             ${0:todo!()}
1335         }
1336     }
1337 }
1338
1339 fn foo() {
1340     bar::baz::my_fn()
1341 }
1342 ",
1343         )
1344     }
1345
1346     #[test]
1347     fn add_function_in_another_file() {
1348         check_assist(
1349             generate_function,
1350             r"
1351 //- /main.rs
1352 mod foo;
1353
1354 fn main() {
1355     foo::bar$0()
1356 }
1357 //- /foo.rs
1358 ",
1359             r"
1360
1361
1362 pub(crate) fn bar() {
1363     ${0:todo!()}
1364 }",
1365         )
1366     }
1367
1368     #[test]
1369     fn add_function_with_return_type() {
1370         check_assist(
1371             generate_function,
1372             r"
1373 fn main() {
1374     let x: u32 = foo$0();
1375 }
1376 ",
1377             r"
1378 fn main() {
1379     let x: u32 = foo();
1380 }
1381
1382 fn foo() -> u32 {
1383     ${0:todo!()}
1384 }
1385 ",
1386         )
1387     }
1388
1389     #[test]
1390     fn add_function_not_applicable_if_function_already_exists() {
1391         check_assist_not_applicable(
1392             generate_function,
1393             r"
1394 fn foo() {
1395     bar$0();
1396 }
1397
1398 fn bar() {}
1399 ",
1400         )
1401     }
1402
1403     #[test]
1404     fn add_function_not_applicable_if_unresolved_variable_in_call_is_selected() {
1405         check_assist_not_applicable(
1406             // bar is resolved, but baz isn't.
1407             // The assist is only active if the cursor is on an unresolved path,
1408             // but the assist should only be offered if the path is a function call.
1409             generate_function,
1410             r#"
1411 fn foo() {
1412     bar(b$0az);
1413 }
1414
1415 fn bar(baz: ()) {}
1416 "#,
1417         )
1418     }
1419
1420     #[test]
1421     fn create_method_with_no_args() {
1422         check_assist(
1423             generate_function,
1424             r#"
1425 struct Foo;
1426 impl Foo {
1427     fn foo(&self) {
1428         self.bar()$0;
1429     }
1430 }
1431 "#,
1432             r#"
1433 struct Foo;
1434 impl Foo {
1435     fn foo(&self) {
1436         self.bar();
1437     }
1438
1439     fn bar(&self) ${0:-> _} {
1440         todo!()
1441     }
1442 }
1443 "#,
1444         )
1445     }
1446
1447     #[test]
1448     fn create_function_with_async() {
1449         check_assist(
1450             generate_function,
1451             r"
1452 fn foo() {
1453     $0bar(42).await();
1454 }
1455 ",
1456             r"
1457 fn foo() {
1458     bar(42).await();
1459 }
1460
1461 async fn bar(arg: i32) ${0:-> _} {
1462     todo!()
1463 }
1464 ",
1465         )
1466     }
1467
1468     #[test]
1469     fn create_method() {
1470         check_assist(
1471             generate_function,
1472             r"
1473 struct S;
1474 fn foo() {S.bar$0();}
1475 ",
1476             r"
1477 struct S;
1478 impl S {
1479     fn bar(&self) ${0:-> _} {
1480         todo!()
1481     }
1482 }
1483 fn foo() {S.bar();}
1484 ",
1485         )
1486     }
1487
1488     #[test]
1489     fn create_method_within_an_impl() {
1490         check_assist(
1491             generate_function,
1492             r"
1493 struct S;
1494 fn foo() {S.bar$0();}
1495 impl S {}
1496
1497 ",
1498             r"
1499 struct S;
1500 fn foo() {S.bar();}
1501 impl S {
1502     fn bar(&self) ${0:-> _} {
1503         todo!()
1504     }
1505 }
1506
1507 ",
1508         )
1509     }
1510
1511     #[test]
1512     fn create_method_from_different_module() {
1513         check_assist(
1514             generate_function,
1515             r"
1516 mod s {
1517     pub struct S;
1518 }
1519 fn foo() {s::S.bar$0();}
1520 ",
1521             r"
1522 mod s {
1523     pub struct S;
1524     impl S {
1525         pub(crate) fn bar(&self) ${0:-> _} {
1526             todo!()
1527         }
1528     }
1529 }
1530 fn foo() {s::S.bar();}
1531 ",
1532         )
1533     }
1534
1535     #[test]
1536     fn create_method_from_descendant_module() {
1537         check_assist(
1538             generate_function,
1539             r"
1540 struct S;
1541 mod s {
1542     fn foo() {
1543         super::S.bar$0();
1544     }
1545 }
1546
1547 ",
1548             r"
1549 struct S;
1550 impl S {
1551     fn bar(&self) ${0:-> _} {
1552         todo!()
1553     }
1554 }
1555 mod s {
1556     fn foo() {
1557         super::S.bar();
1558     }
1559 }
1560
1561 ",
1562         )
1563     }
1564
1565     #[test]
1566     fn create_method_with_cursor_anywhere_on_call_expresion() {
1567         check_assist(
1568             generate_function,
1569             r"
1570 struct S;
1571 fn foo() {$0S.bar();}
1572 ",
1573             r"
1574 struct S;
1575 impl S {
1576     fn bar(&self) ${0:-> _} {
1577         todo!()
1578     }
1579 }
1580 fn foo() {S.bar();}
1581 ",
1582         )
1583     }
1584
1585     #[test]
1586     fn create_static_method() {
1587         check_assist(
1588             generate_function,
1589             r"
1590 struct S;
1591 fn foo() {S::bar$0();}
1592 ",
1593             r"
1594 struct S;
1595 impl S {
1596     fn bar() ${0:-> _} {
1597         todo!()
1598     }
1599 }
1600 fn foo() {S::bar();}
1601 ",
1602         )
1603     }
1604
1605     #[test]
1606     fn create_static_method_within_an_impl() {
1607         check_assist(
1608             generate_function,
1609             r"
1610 struct S;
1611 fn foo() {S::bar$0();}
1612 impl S {}
1613
1614 ",
1615             r"
1616 struct S;
1617 fn foo() {S::bar();}
1618 impl S {
1619     fn bar() ${0:-> _} {
1620         todo!()
1621     }
1622 }
1623
1624 ",
1625         )
1626     }
1627
1628     #[test]
1629     fn create_static_method_from_different_module() {
1630         check_assist(
1631             generate_function,
1632             r"
1633 mod s {
1634     pub struct S;
1635 }
1636 fn foo() {s::S::bar$0();}
1637 ",
1638             r"
1639 mod s {
1640     pub struct S;
1641     impl S {
1642         pub(crate) fn bar() ${0:-> _} {
1643             todo!()
1644         }
1645     }
1646 }
1647 fn foo() {s::S::bar();}
1648 ",
1649         )
1650     }
1651
1652     #[test]
1653     fn create_static_method_with_cursor_anywhere_on_call_expresion() {
1654         check_assist(
1655             generate_function,
1656             r"
1657 struct S;
1658 fn foo() {$0S::bar();}
1659 ",
1660             r"
1661 struct S;
1662 impl S {
1663     fn bar() ${0:-> _} {
1664         todo!()
1665     }
1666 }
1667 fn foo() {S::bar();}
1668 ",
1669         )
1670     }
1671
1672     #[test]
1673     fn create_static_method_within_an_impl_with_self_syntax() {
1674         check_assist(
1675             generate_function,
1676             r"
1677 struct S;
1678 impl S {
1679     fn foo(&self) {
1680         Self::bar$0();
1681     }
1682 }
1683 ",
1684             r"
1685 struct S;
1686 impl S {
1687     fn foo(&self) {
1688         Self::bar();
1689     }
1690
1691     fn bar() ${0:-> _} {
1692         todo!()
1693     }
1694 }
1695 ",
1696         )
1697     }
1698
1699     #[test]
1700     fn no_panic_on_invalid_global_path() {
1701         check_assist(
1702             generate_function,
1703             r"
1704 fn main() {
1705     ::foo$0();
1706 }
1707 ",
1708             r"
1709 fn main() {
1710     ::foo();
1711 }
1712
1713 fn foo() ${0:-> _} {
1714     todo!()
1715 }
1716 ",
1717         )
1718     }
1719
1720     #[test]
1721     fn handle_tuple_indexing() {
1722         check_assist(
1723             generate_function,
1724             r"
1725 fn main() {
1726     let a = ((),);
1727     foo$0(a.0);
1728 }
1729 ",
1730             r"
1731 fn main() {
1732     let a = ((),);
1733     foo(a.0);
1734 }
1735
1736 fn foo(a: ()) ${0:-> _} {
1737     todo!()
1738 }
1739 ",
1740         )
1741     }
1742
1743     #[test]
1744     fn add_function_with_const_arg() {
1745         check_assist(
1746             generate_function,
1747             r"
1748 const VALUE: usize = 0;
1749 fn main() {
1750     foo$0(VALUE);
1751 }
1752 ",
1753             r"
1754 const VALUE: usize = 0;
1755 fn main() {
1756     foo(VALUE);
1757 }
1758
1759 fn foo(value: usize) ${0:-> _} {
1760     todo!()
1761 }
1762 ",
1763         )
1764     }
1765
1766     #[test]
1767     fn add_function_with_static_arg() {
1768         check_assist(
1769             generate_function,
1770             r"
1771 static VALUE: usize = 0;
1772 fn main() {
1773     foo$0(VALUE);
1774 }
1775 ",
1776             r"
1777 static VALUE: usize = 0;
1778 fn main() {
1779     foo(VALUE);
1780 }
1781
1782 fn foo(value: usize) ${0:-> _} {
1783     todo!()
1784 }
1785 ",
1786         )
1787     }
1788
1789     #[test]
1790     fn add_function_with_static_mut_arg() {
1791         check_assist(
1792             generate_function,
1793             r"
1794 static mut VALUE: usize = 0;
1795 fn main() {
1796     foo$0(VALUE);
1797 }
1798 ",
1799             r"
1800 static mut VALUE: usize = 0;
1801 fn main() {
1802     foo(VALUE);
1803 }
1804
1805 fn foo(value: usize) ${0:-> _} {
1806     todo!()
1807 }
1808 ",
1809         )
1810     }
1811
1812     #[test]
1813     fn not_applicable_for_enum_variant() {
1814         check_assist_not_applicable(
1815             generate_function,
1816             r"
1817 enum Foo {}
1818 fn main() {
1819     Foo::Bar$0(true)
1820 }
1821 ",
1822         );
1823     }
1824
1825     #[test]
1826     fn applicable_for_enum_method() {
1827         check_assist(
1828             generate_function,
1829             r"
1830 enum Foo {}
1831 fn main() {
1832     Foo::new$0();
1833 }
1834 ",
1835             r"
1836 enum Foo {}
1837 impl Foo {
1838     fn new() ${0:-> _} {
1839         todo!()
1840     }
1841 }
1842 fn main() {
1843     Foo::new();
1844 }
1845 ",
1846         )
1847     }
1848 }