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