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