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