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