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