• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use hir::{
2     Adt, AsAssocItem, HasSource, HirDisplay, Module, PathResolution, Semantics, Type, TypeInfo,
3 };
4 use ide_db::{
5     base_db::FileId,
6     defs::{Definition, NameRefClass},
7     famous_defs::FamousDefs,
8     helpers::is_editable_crate,
9     path_transform::PathTransform,
10     FxHashMap, FxHashSet, RootDatabase, SnippetCap,
11 };
12 use stdx::to_lower_snake_case;
13 use syntax::{
14     ast::{
15         self,
16         edit::{AstNodeEdit, IndentLevel},
17         make, AstNode, CallExpr, HasArgList, HasGenericParams, HasModuleItem, HasTypeBounds,
18     },
19     SyntaxKind, SyntaxNode, TextRange, TextSize,
20 };
21 
22 use crate::{
23     utils::{convert_reference_type, 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 // ```
generate_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()>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 
gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()>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 TargetInfo { target_module, adt_name, target, file, insert_offset } =
68         fn_target_info(ctx, path, &call, fn_name)?;
69 
70     if let Some(m) = target_module {
71         if !is_editable_crate(m.krate(), ctx.db()) {
72             return None;
73         }
74     }
75 
76     let function_builder = FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target)?;
77     let text_range = call.syntax().text_range();
78     let label = format!("Generate {} function", function_builder.fn_name);
79     add_func_to_accumulator(
80         acc,
81         ctx,
82         text_range,
83         function_builder,
84         insert_offset,
85         file,
86         adt_name,
87         label,
88     )
89 }
90 
91 struct TargetInfo {
92     target_module: Option<Module>,
93     adt_name: Option<hir::Name>,
94     target: GeneratedFunctionTarget,
95     file: FileId,
96     insert_offset: TextSize,
97 }
98 
99 impl TargetInfo {
new( target_module: Option<Module>, adt_name: Option<hir::Name>, target: GeneratedFunctionTarget, file: FileId, insert_offset: TextSize, ) -> Self100     fn new(
101         target_module: Option<Module>,
102         adt_name: Option<hir::Name>,
103         target: GeneratedFunctionTarget,
104         file: FileId,
105         insert_offset: TextSize,
106     ) -> Self {
107         Self { target_module, adt_name, target, file, insert_offset }
108     }
109 }
110 
fn_target_info( ctx: &AssistContext<'_>, path: ast::Path, call: &CallExpr, fn_name: &str, ) -> Option<TargetInfo>111 fn fn_target_info(
112     ctx: &AssistContext<'_>,
113     path: ast::Path,
114     call: &CallExpr,
115     fn_name: &str,
116 ) -> Option<TargetInfo> {
117     match path.qualifier() {
118         Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
119             Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => {
120                 get_fn_target_info(ctx, Some(module), call.clone())
121             }
122             Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
123                 if let hir::Adt::Enum(_) = adt {
124                     // Don't suggest generating function if the name starts with an uppercase letter
125                     if fn_name.starts_with(char::is_uppercase) {
126                         return None;
127                     }
128                 }
129 
130                 assoc_fn_target_info(ctx, call, adt, fn_name)
131             }
132             Some(hir::PathResolution::SelfType(impl_)) => {
133                 let adt = impl_.self_ty(ctx.db()).as_adt()?;
134                 assoc_fn_target_info(ctx, call, adt, fn_name)
135             }
136             _ => None,
137         },
138         _ => get_fn_target_info(ctx, None, call.clone()),
139     }
140 }
141 
gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()>142 fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
143     let call: ast::MethodCallExpr = ctx.find_node_at_offset()?;
144     if ctx.sema.resolve_method_call(&call).is_some() {
145         return None;
146     }
147 
148     let fn_name = call.name_ref()?;
149     let receiver_ty = ctx.sema.type_of_expr(&call.receiver()?)?.original().strip_references();
150     let adt = receiver_ty.as_adt()?;
151 
152     let target_module = adt.module(ctx.sema.db);
153     if !is_editable_crate(target_module.krate(), ctx.db()) {
154         return None;
155     }
156 
157     let (impl_, file) = get_adt_source(ctx, &adt, fn_name.text().as_str())?;
158     let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
159 
160     let function_builder = FunctionBuilder::from_method_call(
161         ctx,
162         &call,
163         &fn_name,
164         receiver_ty,
165         target_module,
166         target,
167     )?;
168     let text_range = call.syntax().text_range();
169     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
170     let label = format!("Generate {} method", function_builder.fn_name);
171     add_func_to_accumulator(
172         acc,
173         ctx,
174         text_range,
175         function_builder,
176         insert_offset,
177         file,
178         adt_name,
179         label,
180     )
181 }
182 
add_func_to_accumulator( acc: &mut Assists, ctx: &AssistContext<'_>, text_range: TextRange, function_builder: FunctionBuilder, insert_offset: TextSize, file: FileId, adt_name: Option<hir::Name>, label: String, ) -> Option<()>183 fn add_func_to_accumulator(
184     acc: &mut Assists,
185     ctx: &AssistContext<'_>,
186     text_range: TextRange,
187     function_builder: FunctionBuilder,
188     insert_offset: TextSize,
189     file: FileId,
190     adt_name: Option<hir::Name>,
191     label: String,
192 ) -> Option<()> {
193     acc.add(AssistId("generate_function", AssistKind::Generate), label, text_range, |builder| {
194         let indent = IndentLevel::from_node(function_builder.target.syntax());
195         let function_template = function_builder.render(adt_name.is_some());
196         let mut func = function_template.to_string(ctx.config.snippet_cap);
197         if let Some(name) = adt_name {
198             // FIXME: adt may have generic params.
199             func = format!("\n{indent}impl {} {{\n{func}\n{indent}}}", name.display(ctx.db()));
200         }
201         builder.edit_file(file);
202         match ctx.config.snippet_cap {
203             Some(cap) => builder.insert_snippet(cap, insert_offset, func),
204             None => builder.insert(insert_offset, func),
205         }
206     })
207 }
208 
get_adt_source( ctx: &AssistContext<'_>, adt: &hir::Adt, fn_name: &str, ) -> Option<(Option<ast::Impl>, FileId)>209 fn get_adt_source(
210     ctx: &AssistContext<'_>,
211     adt: &hir::Adt,
212     fn_name: &str,
213 ) -> Option<(Option<ast::Impl>, FileId)> {
214     let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db);
215     let file = ctx.sema.parse(range.file_id);
216     let adt_source =
217         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
218     find_struct_impl(ctx, &adt_source, &[fn_name.to_string()]).map(|impl_| (impl_, range.file_id))
219 }
220 
221 struct FunctionTemplate {
222     leading_ws: String,
223     fn_def: ast::Fn,
224     ret_type: Option<ast::RetType>,
225     should_focus_return_type: bool,
226     trailing_ws: String,
227     tail_expr: ast::Expr,
228 }
229 
230 impl FunctionTemplate {
to_string(&self, cap: Option<SnippetCap>) -> String231     fn to_string(&self, cap: Option<SnippetCap>) -> String {
232         let Self { leading_ws, fn_def, ret_type, should_focus_return_type, trailing_ws, tail_expr } =
233             self;
234 
235         let f = match cap {
236             Some(cap) => {
237                 let cursor = if *should_focus_return_type {
238                     // Focus the return type if there is one
239                     match ret_type {
240                         Some(ret_type) => ret_type.syntax(),
241                         None => tail_expr.syntax(),
242                     }
243                 } else {
244                     tail_expr.syntax()
245                 };
246                 render_snippet(cap, fn_def.syntax(), Cursor::Replace(cursor))
247             }
248             None => fn_def.to_string(),
249         };
250 
251         format!("{leading_ws}{f}{trailing_ws}")
252     }
253 }
254 
255 struct FunctionBuilder {
256     target: GeneratedFunctionTarget,
257     fn_name: ast::Name,
258     generic_param_list: Option<ast::GenericParamList>,
259     where_clause: Option<ast::WhereClause>,
260     params: ast::ParamList,
261     ret_type: Option<ast::RetType>,
262     should_focus_return_type: bool,
263     visibility: Visibility,
264     is_async: bool,
265 }
266 
267 impl FunctionBuilder {
268     /// Prepares a generated function that matches `call`.
269     /// The function is generated in `target_module` or next to `call`
from_call( ctx: &AssistContext<'_>, call: &ast::CallExpr, fn_name: &str, target_module: Option<Module>, target: GeneratedFunctionTarget, ) -> Option<Self>270     fn from_call(
271         ctx: &AssistContext<'_>,
272         call: &ast::CallExpr,
273         fn_name: &str,
274         target_module: Option<Module>,
275         target: GeneratedFunctionTarget,
276     ) -> Option<Self> {
277         let target_module =
278             target_module.or_else(|| ctx.sema.scope(target.syntax()).map(|it| it.module()))?;
279 
280         let current_module = ctx.sema.scope(call.syntax())?.module();
281         let visibility = calculate_necessary_visibility(current_module, target_module, ctx);
282         let fn_name = make::name(fn_name);
283         let mut necessary_generic_params = FxHashSet::default();
284         let params = fn_args(
285             ctx,
286             target_module,
287             ast::CallableExpr::Call(call.clone()),
288             &mut necessary_generic_params,
289         )?;
290 
291         let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
292         let is_async = await_expr.is_some();
293 
294         let expr_for_ret_ty = await_expr.map_or_else(|| call.clone().into(), |it| it.into());
295         let (ret_type, should_focus_return_type) =
296             make_return_type(ctx, &expr_for_ret_ty, target_module, &mut necessary_generic_params);
297 
298         let (generic_param_list, where_clause) =
299             fn_generic_params(ctx, necessary_generic_params, &target)?;
300 
301         Some(Self {
302             target,
303             fn_name,
304             generic_param_list,
305             where_clause,
306             params,
307             ret_type,
308             should_focus_return_type,
309             visibility,
310             is_async,
311         })
312     }
313 
from_method_call( ctx: &AssistContext<'_>, call: &ast::MethodCallExpr, name: &ast::NameRef, receiver_ty: Type, target_module: Module, target: GeneratedFunctionTarget, ) -> Option<Self>314     fn from_method_call(
315         ctx: &AssistContext<'_>,
316         call: &ast::MethodCallExpr,
317         name: &ast::NameRef,
318         receiver_ty: Type,
319         target_module: Module,
320         target: GeneratedFunctionTarget,
321     ) -> Option<Self> {
322         let current_module = ctx.sema.scope(call.syntax())?.module();
323         let visibility = calculate_necessary_visibility(current_module, target_module, ctx);
324 
325         let fn_name = make::name(&name.text());
326         let mut necessary_generic_params = FxHashSet::default();
327         necessary_generic_params.extend(receiver_ty.generic_params(ctx.db()));
328         let params = fn_args(
329             ctx,
330             target_module,
331             ast::CallableExpr::MethodCall(call.clone()),
332             &mut necessary_generic_params,
333         )?;
334 
335         let await_expr = call.syntax().parent().and_then(ast::AwaitExpr::cast);
336         let is_async = await_expr.is_some();
337 
338         let expr_for_ret_ty = await_expr.map_or_else(|| call.clone().into(), |it| it.into());
339         let (ret_type, should_focus_return_type) =
340             make_return_type(ctx, &expr_for_ret_ty, target_module, &mut necessary_generic_params);
341 
342         let (generic_param_list, where_clause) =
343             fn_generic_params(ctx, necessary_generic_params, &target)?;
344 
345         Some(Self {
346             target,
347             fn_name,
348             generic_param_list,
349             where_clause,
350             params,
351             ret_type,
352             should_focus_return_type,
353             visibility,
354             is_async,
355         })
356     }
357 
render(self, is_method: bool) -> FunctionTemplate358     fn render(self, is_method: bool) -> FunctionTemplate {
359         let placeholder_expr = make::ext::expr_todo();
360         let fn_body = make::block_expr(vec![], Some(placeholder_expr));
361         let visibility = match self.visibility {
362             Visibility::None => None,
363             Visibility::Crate => Some(make::visibility_pub_crate()),
364             Visibility::Pub => Some(make::visibility_pub()),
365         };
366         let mut fn_def = make::fn_(
367             visibility,
368             self.fn_name,
369             self.generic_param_list,
370             self.where_clause,
371             self.params,
372             fn_body,
373             self.ret_type,
374             self.is_async,
375             false, // FIXME : const and unsafe are not handled yet.
376             false,
377         );
378         let leading_ws;
379         let trailing_ws;
380 
381         match self.target {
382             GeneratedFunctionTarget::BehindItem(it) => {
383                 let mut indent = IndentLevel::from_node(&it);
384                 if is_method {
385                     indent = indent + 1;
386                     leading_ws = format!("{indent}");
387                 } else {
388                     leading_ws = format!("\n\n{indent}");
389                 }
390 
391                 fn_def = fn_def.indent(indent);
392                 trailing_ws = String::new();
393             }
394             GeneratedFunctionTarget::InEmptyItemList(it) => {
395                 let indent = IndentLevel::from_node(&it);
396                 let leading_indent = indent + 1;
397                 leading_ws = format!("\n{leading_indent}");
398                 fn_def = fn_def.indent(leading_indent);
399                 trailing_ws = format!("\n{indent}");
400             }
401         };
402 
403         FunctionTemplate {
404             leading_ws,
405             ret_type: fn_def.ret_type(),
406             // PANIC: we guarantee we always create a function body with a tail expr
407             tail_expr: fn_def.body().unwrap().tail_expr().unwrap(),
408             should_focus_return_type: self.should_focus_return_type,
409             fn_def,
410             trailing_ws,
411         }
412     }
413 }
414 
415 /// Makes an optional return type along with whether the return type should be focused by the cursor.
416 /// If we cannot infer what the return type should be, we create a placeholder type.
417 ///
418 /// The rule for whether we focus a return type or not (and thus focus the function body),
419 /// is rather simple:
420 /// * If we could *not* infer what the return type should be, focus it (so the user can fill-in
421 /// the correct return type).
422 /// * If we could infer the return type, don't focus it (and thus focus the function body) so the
423 /// user can change the `todo!` function body.
make_return_type( ctx: &AssistContext<'_>, expr: &ast::Expr, target_module: Module, necessary_generic_params: &mut FxHashSet<hir::GenericParam>, ) -> (Option<ast::RetType>, bool)424 fn make_return_type(
425     ctx: &AssistContext<'_>,
426     expr: &ast::Expr,
427     target_module: Module,
428     necessary_generic_params: &mut FxHashSet<hir::GenericParam>,
429 ) -> (Option<ast::RetType>, bool) {
430     let (ret_ty, should_focus_return_type) = {
431         match ctx.sema.type_of_expr(expr).map(TypeInfo::original) {
432             Some(ty) if ty.is_unknown() => (Some(make::ty_placeholder()), true),
433             None => (Some(make::ty_placeholder()), true),
434             Some(ty) if ty.is_unit() => (None, false),
435             Some(ty) => {
436                 necessary_generic_params.extend(ty.generic_params(ctx.db()));
437                 let rendered = ty.display_source_code(ctx.db(), target_module.into(), true);
438                 match rendered {
439                     Ok(rendered) => (Some(make::ty(&rendered)), false),
440                     Err(_) => (Some(make::ty_placeholder()), true),
441                 }
442             }
443         }
444     };
445     let ret_type = ret_ty.map(make::ret_type);
446     (ret_type, should_focus_return_type)
447 }
448 
get_fn_target_info( ctx: &AssistContext<'_>, target_module: Option<Module>, call: CallExpr, ) -> Option<TargetInfo>449 fn get_fn_target_info(
450     ctx: &AssistContext<'_>,
451     target_module: Option<Module>,
452     call: CallExpr,
453 ) -> Option<TargetInfo> {
454     let (target, file, insert_offset) = get_fn_target(ctx, target_module, call)?;
455     Some(TargetInfo::new(target_module, None, target, file, insert_offset))
456 }
457 
get_fn_target( ctx: &AssistContext<'_>, target_module: Option<Module>, call: CallExpr, ) -> Option<(GeneratedFunctionTarget, FileId, TextSize)>458 fn get_fn_target(
459     ctx: &AssistContext<'_>,
460     target_module: Option<Module>,
461     call: CallExpr,
462 ) -> Option<(GeneratedFunctionTarget, FileId, TextSize)> {
463     let mut file = ctx.file_id();
464     let target = match target_module {
465         Some(target_module) => {
466             let module_source = target_module.definition_source(ctx.db());
467             let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
468             file = in_file;
469             target
470         }
471         None => next_space_for_fn_after_call_site(ast::CallableExpr::Call(call))?,
472     };
473     Some((target.clone(), file, get_insert_offset(&target)))
474 }
475 
get_method_target( ctx: &AssistContext<'_>, impl_: &Option<ast::Impl>, adt: &Adt, ) -> Option<(GeneratedFunctionTarget, TextSize)>476 fn get_method_target(
477     ctx: &AssistContext<'_>,
478     impl_: &Option<ast::Impl>,
479     adt: &Adt,
480 ) -> Option<(GeneratedFunctionTarget, TextSize)> {
481     let target = match impl_ {
482         Some(impl_) => next_space_for_fn_in_impl(impl_)?,
483         None => {
484             GeneratedFunctionTarget::BehindItem(adt.source(ctx.sema.db)?.syntax().value.clone())
485         }
486     };
487     Some((target.clone(), get_insert_offset(&target)))
488 }
489 
assoc_fn_target_info( ctx: &AssistContext<'_>, call: &CallExpr, adt: hir::Adt, fn_name: &str, ) -> Option<TargetInfo>490 fn assoc_fn_target_info(
491     ctx: &AssistContext<'_>,
492     call: &CallExpr,
493     adt: hir::Adt,
494     fn_name: &str,
495 ) -> Option<TargetInfo> {
496     let current_module = ctx.sema.scope(call.syntax())?.module();
497     let module = adt.module(ctx.sema.db);
498     let target_module = if current_module == module { None } else { Some(module) };
499     if current_module.krate() != module.krate() {
500         return None;
501     }
502     let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
503     let (target, insert_offset) = get_method_target(ctx, &impl_, &adt)?;
504     let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
505     Some(TargetInfo::new(target_module, adt_name, target, file, insert_offset))
506 }
507 
get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize508 fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize {
509     match &target {
510         GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
511         GeneratedFunctionTarget::InEmptyItemList(it) => it.text_range().start() + TextSize::of('{'),
512     }
513 }
514 
515 #[derive(Clone)]
516 enum GeneratedFunctionTarget {
517     BehindItem(SyntaxNode),
518     InEmptyItemList(SyntaxNode),
519 }
520 
521 impl GeneratedFunctionTarget {
syntax(&self) -> &SyntaxNode522     fn syntax(&self) -> &SyntaxNode {
523         match self {
524             GeneratedFunctionTarget::BehindItem(it) => it,
525             GeneratedFunctionTarget::InEmptyItemList(it) => it,
526         }
527     }
528 
parent(&self) -> SyntaxNode529     fn parent(&self) -> SyntaxNode {
530         match self {
531             GeneratedFunctionTarget::BehindItem(it) => it.parent().expect("item without parent"),
532             GeneratedFunctionTarget::InEmptyItemList(it) => it.clone(),
533         }
534     }
535 }
536 
537 /// Computes parameter list for the generated function.
fn_args( ctx: &AssistContext<'_>, target_module: Module, call: ast::CallableExpr, necessary_generic_params: &mut FxHashSet<hir::GenericParam>, ) -> Option<ast::ParamList>538 fn fn_args(
539     ctx: &AssistContext<'_>,
540     target_module: Module,
541     call: ast::CallableExpr,
542     necessary_generic_params: &mut FxHashSet<hir::GenericParam>,
543 ) -> Option<ast::ParamList> {
544     let mut arg_names = Vec::new();
545     let mut arg_types = Vec::new();
546     for arg in call.arg_list()?.args() {
547         arg_names.push(fn_arg_name(&ctx.sema, &arg));
548         arg_types.push(fn_arg_type(ctx, target_module, &arg, necessary_generic_params));
549     }
550     deduplicate_arg_names(&mut arg_names);
551     let params = arg_names.into_iter().zip(arg_types).map(|(name, ty)| {
552         make::param(make::ext::simple_ident_pat(make::name(&name)).into(), make::ty(&ty))
553     });
554 
555     Some(make::param_list(
556         match call {
557             ast::CallableExpr::Call(_) => None,
558             ast::CallableExpr::MethodCall(_) => Some(make::self_param()),
559         },
560         params,
561     ))
562 }
563 
564 /// Gets parameter bounds and where predicates in scope and filters out irrelevant ones. Returns
565 /// `None` when it fails to get scope information.
566 ///
567 /// See comment on `filter_unnecessary_bounds()` for what bounds we consider relevant.
568 ///
569 /// NOTE: Generic parameters returned from this function may cause name clash at `target`. We don't
570 /// currently do anything about it because it's actually easy to resolve it after the assist: just
571 /// use the Rename functionality.
fn_generic_params( ctx: &AssistContext<'_>, necessary_params: FxHashSet<hir::GenericParam>, target: &GeneratedFunctionTarget, ) -> Option<(Option<ast::GenericParamList>, Option<ast::WhereClause>)>572 fn fn_generic_params(
573     ctx: &AssistContext<'_>,
574     necessary_params: FxHashSet<hir::GenericParam>,
575     target: &GeneratedFunctionTarget,
576 ) -> Option<(Option<ast::GenericParamList>, Option<ast::WhereClause>)> {
577     if necessary_params.is_empty() {
578         // Not really needed but fast path.
579         return Some((None, None));
580     }
581 
582     // 1. Get generic parameters (with bounds) and where predicates in scope.
583     let (generic_params, where_preds) = params_and_where_preds_in_scope(ctx);
584 
585     // 2. Extract type parameters included in each bound.
586     let mut generic_params = generic_params
587         .into_iter()
588         .filter_map(|it| compute_contained_params_in_generic_param(ctx, it))
589         .collect();
590     let mut where_preds = where_preds
591         .into_iter()
592         .filter_map(|it| compute_contained_params_in_where_pred(ctx, it))
593         .collect();
594 
595     // 3. Filter out unnecessary bounds.
596     filter_unnecessary_bounds(&mut generic_params, &mut where_preds, necessary_params);
597     filter_bounds_in_scope(&mut generic_params, &mut where_preds, ctx, target);
598 
599     let generic_params: Vec<_> =
600         generic_params.into_iter().map(|it| it.node.clone_for_update()).collect();
601     let where_preds: Vec<_> =
602         where_preds.into_iter().map(|it| it.node.clone_for_update()).collect();
603 
604     // 4. Rewrite paths
605     if let Some(param) = generic_params.first() {
606         let source_scope = ctx.sema.scope(param.syntax())?;
607         let target_scope = ctx.sema.scope(&target.parent())?;
608         if source_scope.module() != target_scope.module() {
609             let transform = PathTransform::generic_transformation(&target_scope, &source_scope);
610             let generic_params = generic_params.iter().map(|it| it.syntax());
611             let where_preds = where_preds.iter().map(|it| it.syntax());
612             transform.apply_all(generic_params.chain(where_preds));
613         }
614     }
615 
616     let generic_param_list = make::generic_param_list(generic_params);
617     let where_clause =
618         if where_preds.is_empty() { None } else { Some(make::where_clause(where_preds)) };
619 
620     Some((Some(generic_param_list), where_clause))
621 }
622 
params_and_where_preds_in_scope( ctx: &AssistContext<'_>, ) -> (Vec<ast::GenericParam>, Vec<ast::WherePred>)623 fn params_and_where_preds_in_scope(
624     ctx: &AssistContext<'_>,
625 ) -> (Vec<ast::GenericParam>, Vec<ast::WherePred>) {
626     let Some(body) = containing_body(ctx) else { return Default::default(); };
627 
628     let mut generic_params = Vec::new();
629     let mut where_clauses = Vec::new();
630 
631     // There are two items where generic parameters currently in scope may be declared: the item
632     // the cursor is at, and its parent (if any).
633     //
634     // We handle parent first so that their generic parameters appear first in the generic
635     // parameter list of the function we're generating.
636     let db = ctx.db();
637     if let Some(parent) = body.as_assoc_item(db).map(|it| it.container(db)) {
638         match parent {
639             hir::AssocItemContainer::Impl(it) => {
640                 let (params, clauses) = get_bounds_in_scope(ctx, it);
641                 generic_params.extend(params);
642                 where_clauses.extend(clauses);
643             }
644             hir::AssocItemContainer::Trait(it) => {
645                 let (params, clauses) = get_bounds_in_scope(ctx, it);
646                 generic_params.extend(params);
647                 where_clauses.extend(clauses);
648             }
649         }
650     }
651 
652     // Other defs with body may inherit generic parameters from its parent, but never have their
653     // own generic parameters.
654     if let hir::DefWithBody::Function(it) = body {
655         let (params, clauses) = get_bounds_in_scope(ctx, it);
656         generic_params.extend(params);
657         where_clauses.extend(clauses);
658     }
659 
660     (generic_params, where_clauses)
661 }
662 
containing_body(ctx: &AssistContext<'_>) -> Option<hir::DefWithBody>663 fn containing_body(ctx: &AssistContext<'_>) -> Option<hir::DefWithBody> {
664     let item: ast::Item = ctx.find_node_at_offset()?;
665     let def = match item {
666         ast::Item::Fn(it) => ctx.sema.to_def(&it)?.into(),
667         ast::Item::Const(it) => ctx.sema.to_def(&it)?.into(),
668         ast::Item::Static(it) => ctx.sema.to_def(&it)?.into(),
669         _ => return None,
670     };
671     Some(def)
672 }
673 
get_bounds_in_scope<D>( ctx: &AssistContext<'_>, def: D, ) -> (impl Iterator<Item = ast::GenericParam>, impl Iterator<Item = ast::WherePred>) where D: HasSource, D::Ast: HasGenericParams,674 fn get_bounds_in_scope<D>(
675     ctx: &AssistContext<'_>,
676     def: D,
677 ) -> (impl Iterator<Item = ast::GenericParam>, impl Iterator<Item = ast::WherePred>)
678 where
679     D: HasSource,
680     D::Ast: HasGenericParams,
681 {
682     // This function should be only called with `Impl`, `Trait`, or `Function`, for which it's
683     // infallible to get source ast.
684     let node = ctx.sema.source(def).unwrap().value;
685     let generic_params = node.generic_param_list().into_iter().flat_map(|it| it.generic_params());
686     let where_clauses = node.where_clause().into_iter().flat_map(|it| it.predicates());
687     (generic_params, where_clauses)
688 }
689 
690 #[derive(Debug)]
691 struct ParamBoundWithParams {
692     node: ast::GenericParam,
693     /// Generic parameter `node` introduces.
694     ///
695     /// ```text
696     /// impl<T> S<T> {
697     ///     fn f<U: Trait<T>>() {}
698     ///          ^ this
699     /// }
700     /// ```
701     ///
702     /// `U` in this example.
703     self_ty_param: hir::GenericParam,
704     /// Generic parameters contained in the trait reference of this bound.
705     ///
706     /// ```text
707     /// impl<T> S<T> {
708     ///     fn f<U: Trait<T>>() {}
709     ///             ^^^^^^^^ params in this part
710     /// }
711     /// ```
712     ///
713     /// `T` in this example.
714     other_params: FxHashSet<hir::GenericParam>,
715 }
716 
717 #[derive(Debug)]
718 struct WherePredWithParams {
719     node: ast::WherePred,
720     /// Generic parameters contained in the "self type" of this where predicate.
721     ///
722     /// ```text
723     /// Struct<T, U>: Trait<T, Assoc = V>,
724     /// ^^^^^^^^^^^^ params in this part
725     /// ```
726     ///
727     /// `T` and `U` in this example.
728     self_ty_params: FxHashSet<hir::GenericParam>,
729     /// Generic parameters contained in the trait reference of this where predicate.
730     ///
731     /// ```text
732     /// Struct<T, U>: Trait<T, Assoc = V>,
733     ///               ^^^^^^^^^^^^^^^^^^^ params in this part
734     /// ```
735     ///
736     /// `T` and `V` in this example.
737     other_params: FxHashSet<hir::GenericParam>,
738 }
739 
compute_contained_params_in_generic_param( ctx: &AssistContext<'_>, node: ast::GenericParam, ) -> Option<ParamBoundWithParams>740 fn compute_contained_params_in_generic_param(
741     ctx: &AssistContext<'_>,
742     node: ast::GenericParam,
743 ) -> Option<ParamBoundWithParams> {
744     match &node {
745         ast::GenericParam::TypeParam(ty) => {
746             let self_ty_param = ctx.sema.to_def(ty)?.into();
747 
748             let other_params = ty
749                 .type_bound_list()
750                 .into_iter()
751                 .flat_map(|it| it.bounds())
752                 .flat_map(|bound| bound.syntax().descendants())
753                 .filter_map(|node| filter_generic_params(ctx, node))
754                 .collect();
755 
756             Some(ParamBoundWithParams { node, self_ty_param, other_params })
757         }
758         ast::GenericParam::ConstParam(ct) => {
759             let self_ty_param = ctx.sema.to_def(ct)?.into();
760             Some(ParamBoundWithParams { node, self_ty_param, other_params: FxHashSet::default() })
761         }
762         ast::GenericParam::LifetimeParam(_) => {
763             // FIXME: It might be a good idea to handle lifetime parameters too.
764             None
765         }
766     }
767 }
768 
compute_contained_params_in_where_pred( ctx: &AssistContext<'_>, node: ast::WherePred, ) -> Option<WherePredWithParams>769 fn compute_contained_params_in_where_pred(
770     ctx: &AssistContext<'_>,
771     node: ast::WherePred,
772 ) -> Option<WherePredWithParams> {
773     let self_ty = node.ty()?;
774     let bound_list = node.type_bound_list()?;
775 
776     let self_ty_params = self_ty
777         .syntax()
778         .descendants()
779         .filter_map(|node| filter_generic_params(ctx, node))
780         .collect();
781 
782     let other_params = bound_list
783         .bounds()
784         .flat_map(|bound| bound.syntax().descendants())
785         .filter_map(|node| filter_generic_params(ctx, node))
786         .collect();
787 
788     Some(WherePredWithParams { node, self_ty_params, other_params })
789 }
790 
filter_generic_params(ctx: &AssistContext<'_>, node: SyntaxNode) -> Option<hir::GenericParam>791 fn filter_generic_params(ctx: &AssistContext<'_>, node: SyntaxNode) -> Option<hir::GenericParam> {
792     let path = ast::Path::cast(node)?;
793     match ctx.sema.resolve_path(&path)? {
794         PathResolution::TypeParam(it) => Some(it.into()),
795         PathResolution::ConstParam(it) => Some(it.into()),
796         _ => None,
797     }
798 }
799 
800 /// Filters out irrelevant bounds from `generic_params` and `where_preds`.
801 ///
802 /// Say we have a trait bound `Struct<T>: Trait<U>`. Given `necessary_params`, when is it relevant
803 /// and when not? Some observations:
804 /// - When `necessary_params` contains `T`, it's likely that we want this bound, but now we have
805 /// an extra param to consider: `U`.
806 /// - On the other hand, when `necessary_params` contains `U` (but not `T`), then it's unlikely
807 /// that we want this bound because it doesn't really constrain `U`.
808 ///
809 /// (FIXME?: The latter clause might be overstating. We may want to include the bound if the self
810 /// type does *not* include generic params at all - like `Option<i32>: From<U>`)
811 ///
812 /// Can we make this a bit more formal? Let's define "dependency" between generic parameters and
813 /// trait bounds:
814 /// - A generic parameter `T` depends on a trait bound if `T` appears in the self type (i.e. left
815 /// part) of the bound.
816 /// - A trait bound depends on a generic parameter `T` if `T` appears in the bound.
817 ///
818 /// Using the notion, what we want is all the bounds that params in `necessary_params`
819 /// *transitively* depend on!
820 ///
821 /// Now it's not hard to solve: we build a dependency graph and compute all reachable nodes from
822 /// nodes that represent params in `necessary_params` by usual and boring DFS.
823 ///
824 /// The time complexity is O(|generic_params| + |where_preds| + |necessary_params|).
filter_unnecessary_bounds( generic_params: &mut Vec<ParamBoundWithParams>, where_preds: &mut Vec<WherePredWithParams>, necessary_params: FxHashSet<hir::GenericParam>, )825 fn filter_unnecessary_bounds(
826     generic_params: &mut Vec<ParamBoundWithParams>,
827     where_preds: &mut Vec<WherePredWithParams>,
828     necessary_params: FxHashSet<hir::GenericParam>,
829 ) {
830     // All `self_ty_param` should be unique as they were collected from `ast::GenericParamList`s.
831     let param_map: FxHashMap<hir::GenericParam, usize> =
832         generic_params.iter().map(|it| it.self_ty_param).zip(0..).collect();
833     let param_count = param_map.len();
834     let generic_params_upper_bound = param_count + generic_params.len();
835     let node_count = generic_params_upper_bound + where_preds.len();
836 
837     // | node index range                        | what the node represents |
838     // |-----------------------------------------|--------------------------|
839     // | 0..param_count                          | generic parameter        |
840     // | param_count..generic_params_upper_bound | `ast::GenericParam`      |
841     // | generic_params_upper_bound..node_count  | `ast::WherePred`         |
842     let mut graph = Graph::new(node_count);
843     for (pred, pred_idx) in generic_params.iter().zip(param_count..) {
844         let param_idx = param_map[&pred.self_ty_param];
845         graph.add_edge(param_idx, pred_idx);
846         graph.add_edge(pred_idx, param_idx);
847 
848         for param in &pred.other_params {
849             let param_idx = param_map[param];
850             graph.add_edge(pred_idx, param_idx);
851         }
852     }
853     for (pred, pred_idx) in where_preds.iter().zip(generic_params_upper_bound..) {
854         for param in &pred.self_ty_params {
855             let param_idx = param_map[param];
856             graph.add_edge(param_idx, pred_idx);
857             graph.add_edge(pred_idx, param_idx);
858         }
859         for param in &pred.other_params {
860             let param_idx = param_map[param];
861             graph.add_edge(pred_idx, param_idx);
862         }
863     }
864 
865     let starting_nodes = necessary_params.iter().map(|param| param_map[param]);
866     let reachable = graph.compute_reachable_nodes(starting_nodes);
867 
868     // Not pretty, but effective. If only there were `Vec::retain_index()`...
869     let mut idx = param_count;
870     generic_params.retain(|_| {
871         idx += 1;
872         reachable[idx - 1]
873     });
874     stdx::always!(idx == generic_params_upper_bound, "inconsistent index");
875     where_preds.retain(|_| {
876         idx += 1;
877         reachable[idx - 1]
878     });
879 }
880 
881 /// Filters out bounds from impl if we're generating the function into the same impl we're
882 /// generating from.
filter_bounds_in_scope( generic_params: &mut Vec<ParamBoundWithParams>, where_preds: &mut Vec<WherePredWithParams>, ctx: &AssistContext<'_>, target: &GeneratedFunctionTarget, ) -> Option<()>883 fn filter_bounds_in_scope(
884     generic_params: &mut Vec<ParamBoundWithParams>,
885     where_preds: &mut Vec<WherePredWithParams>,
886     ctx: &AssistContext<'_>,
887     target: &GeneratedFunctionTarget,
888 ) -> Option<()> {
889     let target_impl = target.parent().ancestors().find_map(ast::Impl::cast)?;
890     let target_impl = ctx.sema.to_def(&target_impl)?;
891     // It's sufficient to test only the first element of `generic_params` because of the order of
892     // insertion (see `params_and_where_preds_in_scope()`).
893     let def = generic_params.first()?.self_ty_param.parent();
894     if def != hir::GenericDef::Impl(target_impl) {
895         return None;
896     }
897 
898     // Now we know every element that belongs to an impl would be in scope at `target`, we can
899     // filter them out just by looking at their parent.
900     generic_params.retain(|it| !matches!(it.self_ty_param.parent(), hir::GenericDef::Impl(_)));
901     where_preds.retain(|it| {
902         it.node.syntax().parent().and_then(|it| it.parent()).and_then(ast::Impl::cast).is_none()
903     });
904 
905     Some(())
906 }
907 
908 /// Makes duplicate argument names unique by appending incrementing numbers.
909 ///
910 /// ```
911 /// let mut names: Vec<String> =
912 ///     vec!["foo".into(), "foo".into(), "bar".into(), "baz".into(), "bar".into()];
913 /// deduplicate_arg_names(&mut names);
914 /// let expected: Vec<String> =
915 ///     vec!["foo_1".into(), "foo_2".into(), "bar_1".into(), "baz".into(), "bar_2".into()];
916 /// assert_eq!(names, expected);
917 /// ```
deduplicate_arg_names(arg_names: &mut [String])918 fn deduplicate_arg_names(arg_names: &mut [String]) {
919     let mut arg_name_counts = FxHashMap::default();
920     for name in arg_names.iter() {
921         *arg_name_counts.entry(name).or_insert(0) += 1;
922     }
923     let duplicate_arg_names: FxHashSet<String> = arg_name_counts
924         .into_iter()
925         .filter(|(_, count)| *count >= 2)
926         .map(|(name, _)| name.clone())
927         .collect();
928 
929     let mut counter_per_name = FxHashMap::default();
930     for arg_name in arg_names.iter_mut() {
931         if duplicate_arg_names.contains(arg_name) {
932             let counter = counter_per_name.entry(arg_name.clone()).or_insert(1);
933             arg_name.push('_');
934             arg_name.push_str(&counter.to_string());
935             *counter += 1;
936         }
937     }
938 }
939 
fn_arg_name(sema: &Semantics<'_, RootDatabase>, arg_expr: &ast::Expr) -> String940 fn fn_arg_name(sema: &Semantics<'_, RootDatabase>, arg_expr: &ast::Expr) -> String {
941     let name = (|| match arg_expr {
942         ast::Expr::CastExpr(cast_expr) => Some(fn_arg_name(sema, &cast_expr.expr()?)),
943         expr => {
944             let name_ref = expr
945                 .syntax()
946                 .descendants()
947                 .filter_map(ast::NameRef::cast)
948                 .filter(|name| name.ident_token().is_some())
949                 .last()?;
950             if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_))) =
951                 NameRefClass::classify(sema, &name_ref)
952             {
953                 return Some(name_ref.to_string().to_lowercase());
954             };
955             Some(to_lower_snake_case(&name_ref.to_string()))
956         }
957     })();
958     match name {
959         Some(mut name) if name.starts_with(|c: char| c.is_ascii_digit()) => {
960             name.insert_str(0, "arg");
961             name
962         }
963         Some(name) => name,
964         None => "arg".to_string(),
965     }
966 }
967 
fn_arg_type( ctx: &AssistContext<'_>, target_module: Module, fn_arg: &ast::Expr, generic_params: &mut FxHashSet<hir::GenericParam>, ) -> String968 fn fn_arg_type(
969     ctx: &AssistContext<'_>,
970     target_module: Module,
971     fn_arg: &ast::Expr,
972     generic_params: &mut FxHashSet<hir::GenericParam>,
973 ) -> String {
974     fn maybe_displayed_type(
975         ctx: &AssistContext<'_>,
976         target_module: Module,
977         fn_arg: &ast::Expr,
978         generic_params: &mut FxHashSet<hir::GenericParam>,
979     ) -> Option<String> {
980         let ty = ctx.sema.type_of_expr(fn_arg)?.adjusted();
981         if ty.is_unknown() {
982             return None;
983         }
984 
985         generic_params.extend(ty.generic_params(ctx.db()));
986 
987         if ty.is_reference() || ty.is_mutable_reference() {
988             let famous_defs = &FamousDefs(&ctx.sema, ctx.sema.scope(fn_arg.syntax())?.krate());
989             convert_reference_type(ty.strip_references(), ctx.db(), famous_defs)
990                 .map(|conversion| conversion.convert_type(ctx.db()))
991                 .or_else(|| ty.display_source_code(ctx.db(), target_module.into(), true).ok())
992         } else {
993             ty.display_source_code(ctx.db(), target_module.into(), true).ok()
994         }
995     }
996 
997     maybe_displayed_type(ctx, target_module, fn_arg, generic_params)
998         .unwrap_or_else(|| String::from("_"))
999 }
1000 
1001 /// Returns the position inside the current mod or file
1002 /// directly after the current block
1003 /// We want to write the generated function directly after
1004 /// fns, impls or macro calls, but inside mods
next_space_for_fn_after_call_site(expr: ast::CallableExpr) -> Option<GeneratedFunctionTarget>1005 fn next_space_for_fn_after_call_site(expr: ast::CallableExpr) -> Option<GeneratedFunctionTarget> {
1006     let mut ancestors = expr.syntax().ancestors().peekable();
1007     let mut last_ancestor: Option<SyntaxNode> = None;
1008     while let Some(next_ancestor) = ancestors.next() {
1009         match next_ancestor.kind() {
1010             SyntaxKind::SOURCE_FILE => {
1011                 break;
1012             }
1013             SyntaxKind::ITEM_LIST => {
1014                 if ancestors.peek().map(|a| a.kind()) == Some(SyntaxKind::MODULE) {
1015                     break;
1016                 }
1017             }
1018             _ => {}
1019         }
1020         last_ancestor = Some(next_ancestor);
1021     }
1022     last_ancestor.map(GeneratedFunctionTarget::BehindItem)
1023 }
1024 
next_space_for_fn_in_module( db: &dyn hir::db::ExpandDatabase, module_source: &hir::InFile<hir::ModuleSource>, ) -> Option<(FileId, GeneratedFunctionTarget)>1025 fn next_space_for_fn_in_module(
1026     db: &dyn hir::db::ExpandDatabase,
1027     module_source: &hir::InFile<hir::ModuleSource>,
1028 ) -> Option<(FileId, GeneratedFunctionTarget)> {
1029     let file = module_source.file_id.original_file(db);
1030     let assist_item = match &module_source.value {
1031         hir::ModuleSource::SourceFile(it) => match it.items().last() {
1032             Some(last_item) => GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()),
1033             None => GeneratedFunctionTarget::BehindItem(it.syntax().clone()),
1034         },
1035         hir::ModuleSource::Module(it) => match it.item_list().and_then(|it| it.items().last()) {
1036             Some(last_item) => GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()),
1037             None => GeneratedFunctionTarget::InEmptyItemList(it.item_list()?.syntax().clone()),
1038         },
1039         hir::ModuleSource::BlockExpr(it) => {
1040             if let Some(last_item) =
1041                 it.statements().take_while(|stmt| matches!(stmt, ast::Stmt::Item(_))).last()
1042             {
1043                 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
1044             } else {
1045                 GeneratedFunctionTarget::InEmptyItemList(it.syntax().clone())
1046             }
1047         }
1048     };
1049     Some((file, assist_item))
1050 }
1051 
next_space_for_fn_in_impl(impl_: &ast::Impl) -> Option<GeneratedFunctionTarget>1052 fn next_space_for_fn_in_impl(impl_: &ast::Impl) -> Option<GeneratedFunctionTarget> {
1053     let assoc_item_list = impl_.assoc_item_list()?;
1054     if let Some(last_item) = assoc_item_list.assoc_items().last() {
1055         Some(GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()))
1056     } else {
1057         Some(GeneratedFunctionTarget::InEmptyItemList(assoc_item_list.syntax().clone()))
1058     }
1059 }
1060 
1061 #[derive(Clone, Copy)]
1062 enum Visibility {
1063     None,
1064     Crate,
1065     Pub,
1066 }
1067 
calculate_necessary_visibility( current_module: Module, target_module: Module, ctx: &AssistContext<'_>, ) -> Visibility1068 fn calculate_necessary_visibility(
1069     current_module: Module,
1070     target_module: Module,
1071     ctx: &AssistContext<'_>,
1072 ) -> Visibility {
1073     let db = ctx.db();
1074     let current_module = current_module.nearest_non_block_module(db);
1075     let target_module = target_module.nearest_non_block_module(db);
1076 
1077     if target_module.krate() != current_module.krate() {
1078         Visibility::Pub
1079     } else if current_module.path_to_root(db).contains(&target_module) {
1080         Visibility::None
1081     } else {
1082         Visibility::Crate
1083     }
1084 }
1085 
1086 // This is never intended to be used as a generic graph structure. If there's ever another need of
1087 // graph algorithm, consider adding a library for that (and replace the following).
1088 /// Minimally implemented directed graph structure represented by adjacency list.
1089 struct Graph {
1090     edges: Vec<Vec<usize>>,
1091 }
1092 
1093 impl Graph {
new(node_count: usize) -> Self1094     fn new(node_count: usize) -> Self {
1095         Self { edges: vec![Vec::new(); node_count] }
1096     }
1097 
add_edge(&mut self, from: usize, to: usize)1098     fn add_edge(&mut self, from: usize, to: usize) {
1099         self.edges[from].push(to);
1100     }
1101 
edges_for(&self, node_idx: usize) -> &[usize]1102     fn edges_for(&self, node_idx: usize) -> &[usize] {
1103         &self.edges[node_idx]
1104     }
1105 
len(&self) -> usize1106     fn len(&self) -> usize {
1107         self.edges.len()
1108     }
1109 
compute_reachable_nodes( &self, starting_nodes: impl IntoIterator<Item = usize>, ) -> Vec<bool>1110     fn compute_reachable_nodes(
1111         &self,
1112         starting_nodes: impl IntoIterator<Item = usize>,
1113     ) -> Vec<bool> {
1114         let mut visitor = Visitor::new(self);
1115         for idx in starting_nodes {
1116             visitor.mark_reachable(idx);
1117         }
1118         visitor.visited
1119     }
1120 }
1121 
1122 struct Visitor<'g> {
1123     graph: &'g Graph,
1124     visited: Vec<bool>,
1125     // Stack is held in this struct so we can reuse its buffer.
1126     stack: Vec<usize>,
1127 }
1128 
1129 impl<'g> Visitor<'g> {
new(graph: &'g Graph) -> Self1130     fn new(graph: &'g Graph) -> Self {
1131         let visited = vec![false; graph.len()];
1132         Self { graph, visited, stack: Vec::new() }
1133     }
1134 
mark_reachable(&mut self, start_idx: usize)1135     fn mark_reachable(&mut self, start_idx: usize) {
1136         // non-recursive DFS
1137         stdx::always!(self.stack.is_empty());
1138 
1139         self.stack.push(start_idx);
1140         while let Some(idx) = self.stack.pop() {
1141             if !self.visited[idx] {
1142                 self.visited[idx] = true;
1143                 for &neighbor in self.graph.edges_for(idx) {
1144                     if !self.visited[neighbor] {
1145                         self.stack.push(neighbor);
1146                     }
1147                 }
1148             }
1149         }
1150     }
1151 }
1152 
1153 #[cfg(test)]
1154 mod tests {
1155     use crate::tests::{check_assist, check_assist_not_applicable};
1156 
1157     use super::*;
1158 
1159     #[test]
add_function_with_no_args()1160     fn add_function_with_no_args() {
1161         check_assist(
1162             generate_function,
1163             r"
1164 fn foo() {
1165     bar$0();
1166 }
1167 ",
1168             r"
1169 fn foo() {
1170     bar();
1171 }
1172 
1173 fn bar() ${0:-> _} {
1174     todo!()
1175 }
1176 ",
1177         )
1178     }
1179 
1180     #[test]
add_function_from_method()1181     fn add_function_from_method() {
1182         // This ensures that the function is correctly generated
1183         // in the next outer mod or file
1184         check_assist(
1185             generate_function,
1186             r"
1187 impl Foo {
1188     fn foo() {
1189         bar$0();
1190     }
1191 }
1192 ",
1193             r"
1194 impl Foo {
1195     fn foo() {
1196         bar();
1197     }
1198 }
1199 
1200 fn bar() ${0:-> _} {
1201     todo!()
1202 }
1203 ",
1204         )
1205     }
1206 
1207     #[test]
add_function_directly_after_current_block()1208     fn add_function_directly_after_current_block() {
1209         // The new fn should not be created at the end of the file or module
1210         check_assist(
1211             generate_function,
1212             r"
1213 fn foo1() {
1214     bar$0();
1215 }
1216 
1217 fn foo2() {}
1218 ",
1219             r"
1220 fn foo1() {
1221     bar();
1222 }
1223 
1224 fn bar() ${0:-> _} {
1225     todo!()
1226 }
1227 
1228 fn foo2() {}
1229 ",
1230         )
1231     }
1232 
1233     #[test]
add_function_with_no_args_in_same_module()1234     fn add_function_with_no_args_in_same_module() {
1235         check_assist(
1236             generate_function,
1237             r"
1238 mod baz {
1239     fn foo() {
1240         bar$0();
1241     }
1242 }
1243 ",
1244             r"
1245 mod baz {
1246     fn foo() {
1247         bar();
1248     }
1249 
1250     fn bar() ${0:-> _} {
1251         todo!()
1252     }
1253 }
1254 ",
1255         )
1256     }
1257 
1258     #[test]
add_function_with_upper_camel_case_arg()1259     fn add_function_with_upper_camel_case_arg() {
1260         check_assist(
1261             generate_function,
1262             r"
1263 struct BazBaz;
1264 fn foo() {
1265     bar$0(BazBaz);
1266 }
1267 ",
1268             r"
1269 struct BazBaz;
1270 fn foo() {
1271     bar(BazBaz);
1272 }
1273 
1274 fn bar(baz_baz: BazBaz) ${0:-> _} {
1275     todo!()
1276 }
1277 ",
1278         );
1279     }
1280 
1281     #[test]
add_function_with_upper_camel_case_arg_as_cast()1282     fn add_function_with_upper_camel_case_arg_as_cast() {
1283         check_assist(
1284             generate_function,
1285             r"
1286 struct BazBaz;
1287 fn foo() {
1288     bar$0(&BazBaz as *const BazBaz);
1289 }
1290 ",
1291             r"
1292 struct BazBaz;
1293 fn foo() {
1294     bar(&BazBaz as *const BazBaz);
1295 }
1296 
1297 fn bar(baz_baz: *const BazBaz) ${0:-> _} {
1298     todo!()
1299 }
1300 ",
1301         );
1302     }
1303 
1304     #[test]
add_function_with_function_call_arg()1305     fn add_function_with_function_call_arg() {
1306         check_assist(
1307             generate_function,
1308             r"
1309 struct Baz;
1310 fn baz() -> Baz { todo!() }
1311 fn foo() {
1312     bar$0(baz());
1313 }
1314 ",
1315             r"
1316 struct Baz;
1317 fn baz() -> Baz { todo!() }
1318 fn foo() {
1319     bar(baz());
1320 }
1321 
1322 fn bar(baz: Baz) ${0:-> _} {
1323     todo!()
1324 }
1325 ",
1326         );
1327     }
1328 
1329     #[test]
add_function_with_method_call_arg()1330     fn add_function_with_method_call_arg() {
1331         check_assist(
1332             generate_function,
1333             r"
1334 struct Baz;
1335 impl Baz {
1336     fn foo(&self) -> Baz {
1337         ba$0r(self.baz())
1338     }
1339     fn baz(&self) -> Baz {
1340         Baz
1341     }
1342 }
1343 ",
1344             r"
1345 struct Baz;
1346 impl Baz {
1347     fn foo(&self) -> Baz {
1348         bar(self.baz())
1349     }
1350     fn baz(&self) -> Baz {
1351         Baz
1352     }
1353 }
1354 
1355 fn bar(baz: Baz) -> Baz {
1356     ${0:todo!()}
1357 }
1358 ",
1359         )
1360     }
1361 
1362     #[test]
add_function_with_string_literal_arg()1363     fn add_function_with_string_literal_arg() {
1364         check_assist(
1365             generate_function,
1366             r#"
1367 fn foo() {
1368     $0bar("bar")
1369 }
1370 "#,
1371             r#"
1372 fn foo() {
1373     bar("bar")
1374 }
1375 
1376 fn bar(arg: &str) {
1377     ${0:todo!()}
1378 }
1379 "#,
1380         )
1381     }
1382 
1383     #[test]
add_function_with_char_literal_arg()1384     fn add_function_with_char_literal_arg() {
1385         check_assist(
1386             generate_function,
1387             r#"
1388 fn foo() {
1389     $0bar('x')
1390 }
1391 "#,
1392             r#"
1393 fn foo() {
1394     bar('x')
1395 }
1396 
1397 fn bar(arg: char) {
1398     ${0:todo!()}
1399 }
1400 "#,
1401         )
1402     }
1403 
1404     #[test]
add_function_with_int_literal_arg()1405     fn add_function_with_int_literal_arg() {
1406         check_assist(
1407             generate_function,
1408             r"
1409 fn foo() {
1410     $0bar(42)
1411 }
1412 ",
1413             r"
1414 fn foo() {
1415     bar(42)
1416 }
1417 
1418 fn bar(arg: i32) {
1419     ${0:todo!()}
1420 }
1421 ",
1422         )
1423     }
1424 
1425     #[test]
add_function_with_cast_int_literal_arg()1426     fn add_function_with_cast_int_literal_arg() {
1427         check_assist(
1428             generate_function,
1429             r"
1430 fn foo() {
1431     $0bar(42 as u8)
1432 }
1433 ",
1434             r"
1435 fn foo() {
1436     bar(42 as u8)
1437 }
1438 
1439 fn bar(arg: u8) {
1440     ${0:todo!()}
1441 }
1442 ",
1443         )
1444     }
1445 
1446     #[test]
name_of_cast_variable_is_used()1447     fn name_of_cast_variable_is_used() {
1448         // Ensures that the name of the cast type isn't used
1449         // in the generated function signature.
1450         check_assist(
1451             generate_function,
1452             r"
1453 fn foo() {
1454     let x = 42;
1455     bar$0(x as u8)
1456 }
1457 ",
1458             r"
1459 fn foo() {
1460     let x = 42;
1461     bar(x as u8)
1462 }
1463 
1464 fn bar(x: u8) {
1465     ${0:todo!()}
1466 }
1467 ",
1468         )
1469     }
1470 
1471     #[test]
add_function_with_variable_arg()1472     fn add_function_with_variable_arg() {
1473         check_assist(
1474             generate_function,
1475             r"
1476 fn foo() {
1477     let worble = ();
1478     $0bar(worble)
1479 }
1480 ",
1481             r"
1482 fn foo() {
1483     let worble = ();
1484     bar(worble)
1485 }
1486 
1487 fn bar(worble: ()) {
1488     ${0:todo!()}
1489 }
1490 ",
1491         )
1492     }
1493 
1494     #[test]
add_function_with_impl_trait_arg()1495     fn add_function_with_impl_trait_arg() {
1496         check_assist(
1497             generate_function,
1498             r#"
1499 //- minicore: sized
1500 trait Foo {}
1501 fn foo() -> impl Foo {
1502     todo!()
1503 }
1504 fn baz() {
1505     $0bar(foo())
1506 }
1507 "#,
1508             r#"
1509 trait Foo {}
1510 fn foo() -> impl Foo {
1511     todo!()
1512 }
1513 fn baz() {
1514     bar(foo())
1515 }
1516 
1517 fn bar(foo: impl Foo) {
1518     ${0:todo!()}
1519 }
1520 "#,
1521         )
1522     }
1523 
1524     #[test]
borrowed_arg()1525     fn borrowed_arg() {
1526         check_assist(
1527             generate_function,
1528             r"
1529 struct Baz;
1530 fn baz() -> Baz { todo!() }
1531 
1532 fn foo() {
1533     bar$0(&baz())
1534 }
1535 ",
1536             r"
1537 struct Baz;
1538 fn baz() -> Baz { todo!() }
1539 
1540 fn foo() {
1541     bar(&baz())
1542 }
1543 
1544 fn bar(baz: &Baz) {
1545     ${0:todo!()}
1546 }
1547 ",
1548         )
1549     }
1550 
1551     #[test]
add_function_with_qualified_path_arg()1552     fn add_function_with_qualified_path_arg() {
1553         check_assist(
1554             generate_function,
1555             r"
1556 mod Baz {
1557     pub struct Bof;
1558     pub fn baz() -> Bof { Bof }
1559 }
1560 fn foo() {
1561     $0bar(Baz::baz())
1562 }
1563 ",
1564             r"
1565 mod Baz {
1566     pub struct Bof;
1567     pub fn baz() -> Bof { Bof }
1568 }
1569 fn foo() {
1570     bar(Baz::baz())
1571 }
1572 
1573 fn bar(baz: Baz::Bof) {
1574     ${0:todo!()}
1575 }
1576 ",
1577         )
1578     }
1579 
1580     #[test]
generate_function_with_generic_param()1581     fn generate_function_with_generic_param() {
1582         check_assist(
1583             generate_function,
1584             r"
1585 fn foo<T, const N: usize>(t: [T; N]) { $0bar(t) }
1586 ",
1587             r"
1588 fn foo<T, const N: usize>(t: [T; N]) { bar(t) }
1589 
1590 fn bar<T, const N: usize>(t: [T; N]) {
1591     ${0:todo!()}
1592 }
1593 ",
1594         )
1595     }
1596 
1597     #[test]
generate_function_with_parent_generic_param()1598     fn generate_function_with_parent_generic_param() {
1599         check_assist(
1600             generate_function,
1601             r"
1602 struct S<T>(T);
1603 impl<T> S<T> {
1604     fn foo<U>(t: T, u: U) { $0bar(t, u) }
1605 }
1606 ",
1607             r"
1608 struct S<T>(T);
1609 impl<T> S<T> {
1610     fn foo<U>(t: T, u: U) { bar(t, u) }
1611 }
1612 
1613 fn bar<T, U>(t: T, u: U) {
1614     ${0:todo!()}
1615 }
1616 ",
1617         )
1618     }
1619 
1620     #[test]
generic_param_in_receiver_type()1621     fn generic_param_in_receiver_type() {
1622         // FIXME: Generic parameter `T` should be part of impl, not method.
1623         check_assist(
1624             generate_function,
1625             r"
1626 struct S<T>(T);
1627 fn foo<T, U>(s: S<T>, u: U) { s.$0foo(u) }
1628 ",
1629             r"
1630 struct S<T>(T);
1631 impl S {
1632     fn foo<T, U>(&self, u: U) {
1633         ${0:todo!()}
1634     }
1635 }
1636 fn foo<T, U>(s: S<T>, u: U) { s.foo(u) }
1637 ",
1638         )
1639     }
1640 
1641     #[test]
generic_param_in_return_type()1642     fn generic_param_in_return_type() {
1643         check_assist(
1644             generate_function,
1645             r"
1646 fn foo<T, const N: usize>() -> [T; N] { $0bar() }
1647 ",
1648             r"
1649 fn foo<T, const N: usize>() -> [T; N] { bar() }
1650 
1651 fn bar<T, const N: usize>() -> [T; N] {
1652     ${0:todo!()}
1653 }
1654 ",
1655         )
1656     }
1657 
1658     #[test]
generate_fn_with_bounds()1659     fn generate_fn_with_bounds() {
1660         // FIXME: where predicates should be on next lines.
1661         check_assist(
1662             generate_function,
1663             r"
1664 trait A<T> {}
1665 struct S<T>(T);
1666 impl<T: A<i32>> S<T>
1667 where
1668     T: A<i64>,
1669 {
1670     fn foo<U>(t: T, u: U)
1671     where
1672         T: A<()>,
1673         U: A<i32> + A<i64>,
1674     {
1675         $0bar(t, u)
1676     }
1677 }
1678 ",
1679             r"
1680 trait A<T> {}
1681 struct S<T>(T);
1682 impl<T: A<i32>> S<T>
1683 where
1684     T: A<i64>,
1685 {
1686     fn foo<U>(t: T, u: U)
1687     where
1688         T: A<()>,
1689         U: A<i32> + A<i64>,
1690     {
1691         bar(t, u)
1692     }
1693 }
1694 
1695 fn bar<T: A<i32>, U>(t: T, u: U) where T: A<i64>, T: A<()>, U: A<i32> + A<i64> {
1696     ${0:todo!()}
1697 }
1698 ",
1699         )
1700     }
1701 
1702     #[test]
include_transitive_param_dependency()1703     fn include_transitive_param_dependency() {
1704         // FIXME: where predicates should be on next lines.
1705         check_assist(
1706             generate_function,
1707             r"
1708 trait A<T> { type Assoc; }
1709 trait B { type Item; }
1710 struct S<T>(T);
1711 impl<T, U, V: B, W> S<(T, U, V, W)>
1712 where
1713     T: A<U, Assoc = V>,
1714     S<V::Item>: A<U, Assoc = W>,
1715 {
1716     fn foo<I>(t: T, u: U)
1717     where
1718         U: A<T, Assoc = I>,
1719     {
1720         $0bar(u)
1721     }
1722 }
1723 ",
1724             r"
1725 trait A<T> { type Assoc; }
1726 trait B { type Item; }
1727 struct S<T>(T);
1728 impl<T, U, V: B, W> S<(T, U, V, W)>
1729 where
1730     T: A<U, Assoc = V>,
1731     S<V::Item>: A<U, Assoc = W>,
1732 {
1733     fn foo<I>(t: T, u: U)
1734     where
1735         U: A<T, Assoc = I>,
1736     {
1737         bar(u)
1738     }
1739 }
1740 
1741 fn bar<T, U, V: B, W, I>(u: U) where T: A<U, Assoc = V>, S<V::Item>: A<U, Assoc = W>, U: A<T, Assoc = I> {
1742     ${0:todo!()}
1743 }
1744 ",
1745         )
1746     }
1747 
1748     #[test]
irrelevant_bounds_are_filtered_out()1749     fn irrelevant_bounds_are_filtered_out() {
1750         check_assist(
1751             generate_function,
1752             r"
1753 trait A<T> {}
1754 struct S<T>(T);
1755 impl<T, U, V, W> S<(T, U, V, W)>
1756 where
1757     T: A<U>,
1758     V: A<W>,
1759 {
1760     fn foo<I>(t: T, u: U)
1761     where
1762         U: A<T> + A<I>,
1763     {
1764         $0bar(u)
1765     }
1766 }
1767 ",
1768             r"
1769 trait A<T> {}
1770 struct S<T>(T);
1771 impl<T, U, V, W> S<(T, U, V, W)>
1772 where
1773     T: A<U>,
1774     V: A<W>,
1775 {
1776     fn foo<I>(t: T, u: U)
1777     where
1778         U: A<T> + A<I>,
1779     {
1780         bar(u)
1781     }
1782 }
1783 
1784 fn bar<T, U, I>(u: U) where T: A<U>, U: A<T> + A<I> {
1785     ${0:todo!()}
1786 }
1787 ",
1788         )
1789     }
1790 
1791     #[test]
params_in_trait_arg_are_not_dependency()1792     fn params_in_trait_arg_are_not_dependency() {
1793         // Even though `bar` depends on `U` and `I`, we don't have to copy these bounds:
1794         // `T: A<I>` and `T: A<U>`.
1795         check_assist(
1796             generate_function,
1797             r"
1798 trait A<T> {}
1799 struct S<T>(T);
1800 impl<T, U> S<(T, U)>
1801 where
1802     T: A<U>,
1803 {
1804     fn foo<I>(t: T, u: U)
1805     where
1806         T: A<I>,
1807         U: A<I>,
1808     {
1809         $0bar(u)
1810     }
1811 }
1812 ",
1813             r"
1814 trait A<T> {}
1815 struct S<T>(T);
1816 impl<T, U> S<(T, U)>
1817 where
1818     T: A<U>,
1819 {
1820     fn foo<I>(t: T, u: U)
1821     where
1822         T: A<I>,
1823         U: A<I>,
1824     {
1825         bar(u)
1826     }
1827 }
1828 
1829 fn bar<U, I>(u: U) where U: A<I> {
1830     ${0:todo!()}
1831 }
1832 ",
1833         )
1834     }
1835 
1836     #[test]
dont_copy_bounds_already_in_scope()1837     fn dont_copy_bounds_already_in_scope() {
1838         check_assist(
1839             generate_function,
1840             r"
1841 trait A<T> {}
1842 struct S<T>(T);
1843 impl<T: A<i32>> S<T>
1844 where
1845     T: A<usize>,
1846 {
1847     fn foo<U: A<()>>(t: T, u: U)
1848     where
1849         T: A<S<i32>>,
1850     {
1851         Self::$0bar(t, u);
1852     }
1853 }
1854 ",
1855             r"
1856 trait A<T> {}
1857 struct S<T>(T);
1858 impl<T: A<i32>> S<T>
1859 where
1860     T: A<usize>,
1861 {
1862     fn foo<U: A<()>>(t: T, u: U)
1863     where
1864         T: A<S<i32>>,
1865     {
1866         Self::bar(t, u);
1867     }
1868 
1869     fn bar<U: A<()>>(t: T, u: U) ${0:-> _} where T: A<S<i32>> {
1870         todo!()
1871     }
1872 }
1873 ",
1874         )
1875     }
1876 
1877     #[test]
add_function_with_fn_arg()1878     fn add_function_with_fn_arg() {
1879         // FIXME: The argument in `bar` is wrong.
1880         check_assist(
1881             generate_function,
1882             r"
1883 struct Baz;
1884 impl Baz {
1885     fn new() -> Self { Baz }
1886 }
1887 fn foo() {
1888     $0bar(Baz::new);
1889 }
1890 ",
1891             r"
1892 struct Baz;
1893 impl Baz {
1894     fn new() -> Self { Baz }
1895 }
1896 fn foo() {
1897     bar(Baz::new);
1898 }
1899 
1900 fn bar(new: fn) ${0:-> _} {
1901     todo!()
1902 }
1903 ",
1904         )
1905     }
1906 
1907     #[test]
add_function_with_closure_arg()1908     fn add_function_with_closure_arg() {
1909         check_assist(
1910             generate_function,
1911             r"
1912 fn foo() {
1913     let closure = |x: i64| x - 1;
1914     $0bar(closure)
1915 }
1916 ",
1917             r"
1918 fn foo() {
1919     let closure = |x: i64| x - 1;
1920     bar(closure)
1921 }
1922 
1923 fn bar(closure: impl Fn(i64) -> i64) {
1924     ${0:todo!()}
1925 }
1926 ",
1927         )
1928     }
1929 
1930     #[test]
unresolveable_types_default_to_placeholder()1931     fn unresolveable_types_default_to_placeholder() {
1932         check_assist(
1933             generate_function,
1934             r"
1935 fn foo() {
1936     $0bar(baz)
1937 }
1938 ",
1939             r"
1940 fn foo() {
1941     bar(baz)
1942 }
1943 
1944 fn bar(baz: _) {
1945     ${0:todo!()}
1946 }
1947 ",
1948         )
1949     }
1950 
1951     #[test]
arg_names_dont_overlap()1952     fn arg_names_dont_overlap() {
1953         check_assist(
1954             generate_function,
1955             r"
1956 struct Baz;
1957 fn baz() -> Baz { Baz }
1958 fn foo() {
1959     $0bar(baz(), baz())
1960 }
1961 ",
1962             r"
1963 struct Baz;
1964 fn baz() -> Baz { Baz }
1965 fn foo() {
1966     bar(baz(), baz())
1967 }
1968 
1969 fn bar(baz_1: Baz, baz_2: Baz) {
1970     ${0:todo!()}
1971 }
1972 ",
1973         )
1974     }
1975 
1976     #[test]
arg_name_counters_start_at_1_per_name()1977     fn arg_name_counters_start_at_1_per_name() {
1978         check_assist(
1979             generate_function,
1980             r#"
1981 struct Baz;
1982 fn baz() -> Baz { Baz }
1983 fn foo() {
1984     $0bar(baz(), baz(), "foo", "bar")
1985 }
1986 "#,
1987             r#"
1988 struct Baz;
1989 fn baz() -> Baz { Baz }
1990 fn foo() {
1991     bar(baz(), baz(), "foo", "bar")
1992 }
1993 
1994 fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) {
1995     ${0:todo!()}
1996 }
1997 "#,
1998         )
1999     }
2000 
2001     #[test]
add_function_in_module()2002     fn add_function_in_module() {
2003         check_assist(
2004             generate_function,
2005             r"
2006 mod bar {}
2007 
2008 fn foo() {
2009     bar::my_fn$0()
2010 }
2011 ",
2012             r"
2013 mod bar {
2014     pub(crate) fn my_fn() {
2015         ${0:todo!()}
2016     }
2017 }
2018 
2019 fn foo() {
2020     bar::my_fn()
2021 }
2022 ",
2023         )
2024     }
2025 
2026     #[test]
qualified_path_uses_correct_scope()2027     fn qualified_path_uses_correct_scope() {
2028         check_assist(
2029             generate_function,
2030             r#"
2031 mod foo {
2032     pub struct Foo;
2033 }
2034 fn bar() {
2035     use foo::Foo;
2036     let foo = Foo;
2037     baz$0(foo)
2038 }
2039 "#,
2040             r#"
2041 mod foo {
2042     pub struct Foo;
2043 }
2044 fn bar() {
2045     use foo::Foo;
2046     let foo = Foo;
2047     baz(foo)
2048 }
2049 
2050 fn baz(foo: foo::Foo) {
2051     ${0:todo!()}
2052 }
2053 "#,
2054         )
2055     }
2056 
2057     #[test]
qualified_path_in_generic_bounds_uses_correct_scope()2058     fn qualified_path_in_generic_bounds_uses_correct_scope() {
2059         check_assist(
2060             generate_function,
2061             r"
2062 mod a {
2063     pub trait A {};
2064 }
2065 pub mod b {
2066     pub struct S<T>(T);
2067 }
2068 struct S<T>(T);
2069 impl<T> S<T>
2070 where
2071     T: a::A,
2072 {
2073     fn foo<U: a::A>(t: b::S<T>, u: S<U>) {
2074         a::$0bar(t, u);
2075     }
2076 }
2077 ",
2078             r"
2079 mod a {
2080     pub trait A {}
2081 
2082     pub(crate) fn bar<T, U: self::A>(t: crate::b::S<T>, u: crate::S<U>) ${0:-> _} where T: self::A {
2083         todo!()
2084     };
2085 }
2086 pub mod b {
2087     pub struct S<T>(T);
2088 }
2089 struct S<T>(T);
2090 impl<T> S<T>
2091 where
2092     T: a::A,
2093 {
2094     fn foo<U: a::A>(t: b::S<T>, u: S<U>) {
2095         a::bar(t, u);
2096     }
2097 }
2098 ",
2099         )
2100     }
2101     #[test]
add_function_in_module_containing_other_items()2102     fn add_function_in_module_containing_other_items() {
2103         check_assist(
2104             generate_function,
2105             r"
2106 mod bar {
2107     fn something_else() {}
2108 }
2109 
2110 fn foo() {
2111     bar::my_fn$0()
2112 }
2113 ",
2114             r"
2115 mod bar {
2116     fn something_else() {}
2117 
2118     pub(crate) fn my_fn() {
2119         ${0:todo!()}
2120     }
2121 }
2122 
2123 fn foo() {
2124     bar::my_fn()
2125 }
2126 ",
2127         )
2128     }
2129 
2130     #[test]
add_function_in_nested_module()2131     fn add_function_in_nested_module() {
2132         check_assist(
2133             generate_function,
2134             r"
2135 mod bar {
2136     pub mod baz {}
2137 }
2138 
2139 fn foo() {
2140     bar::baz::my_fn$0()
2141 }
2142 ",
2143             r"
2144 mod bar {
2145     pub mod baz {
2146         pub(crate) fn my_fn() {
2147             ${0:todo!()}
2148         }
2149     }
2150 }
2151 
2152 fn foo() {
2153     bar::baz::my_fn()
2154 }
2155 ",
2156         )
2157     }
2158 
2159     #[test]
add_function_in_another_file()2160     fn add_function_in_another_file() {
2161         check_assist(
2162             generate_function,
2163             r"
2164 //- /main.rs
2165 mod foo;
2166 
2167 fn main() {
2168     foo::bar$0()
2169 }
2170 //- /foo.rs
2171 ",
2172             r"
2173 
2174 
2175 pub(crate) fn bar() {
2176     ${0:todo!()}
2177 }",
2178         )
2179     }
2180 
2181     #[test]
add_function_with_return_type()2182     fn add_function_with_return_type() {
2183         check_assist(
2184             generate_function,
2185             r"
2186 fn main() {
2187     let x: u32 = foo$0();
2188 }
2189 ",
2190             r"
2191 fn main() {
2192     let x: u32 = foo();
2193 }
2194 
2195 fn foo() -> u32 {
2196     ${0:todo!()}
2197 }
2198 ",
2199         )
2200     }
2201 
2202     #[test]
add_function_not_applicable_if_function_already_exists()2203     fn add_function_not_applicable_if_function_already_exists() {
2204         check_assist_not_applicable(
2205             generate_function,
2206             r"
2207 fn foo() {
2208     bar$0();
2209 }
2210 
2211 fn bar() {}
2212 ",
2213         )
2214     }
2215 
2216     #[test]
add_function_not_applicable_if_unresolved_variable_in_call_is_selected()2217     fn add_function_not_applicable_if_unresolved_variable_in_call_is_selected() {
2218         check_assist_not_applicable(
2219             // bar is resolved, but baz isn't.
2220             // The assist is only active if the cursor is on an unresolved path,
2221             // but the assist should only be offered if the path is a function call.
2222             generate_function,
2223             r#"
2224 fn foo() {
2225     bar(b$0az);
2226 }
2227 
2228 fn bar(baz: ()) {}
2229 "#,
2230         )
2231     }
2232 
2233     #[test]
create_method_with_no_args()2234     fn create_method_with_no_args() {
2235         check_assist(
2236             generate_function,
2237             r#"
2238 struct Foo;
2239 impl Foo {
2240     fn foo(&self) {
2241         self.bar()$0;
2242     }
2243 }
2244 "#,
2245             r#"
2246 struct Foo;
2247 impl Foo {
2248     fn foo(&self) {
2249         self.bar();
2250     }
2251 
2252     fn bar(&self) ${0:-> _} {
2253         todo!()
2254     }
2255 }
2256 "#,
2257         )
2258     }
2259 
2260     #[test]
create_function_with_async()2261     fn create_function_with_async() {
2262         check_assist(
2263             generate_function,
2264             r"
2265 async fn foo() {
2266     $0bar(42).await;
2267 }
2268 ",
2269             r"
2270 async fn foo() {
2271     bar(42).await;
2272 }
2273 
2274 async fn bar(arg: i32) ${0:-> _} {
2275     todo!()
2276 }
2277 ",
2278         )
2279     }
2280 
2281     #[test]
return_type_for_async_fn()2282     fn return_type_for_async_fn() {
2283         check_assist(
2284             generate_function,
2285             r"
2286 //- minicore: result
2287 async fn foo() {
2288     if Err(()) = $0bar(42).await {}
2289 }
2290 ",
2291             r"
2292 async fn foo() {
2293     if Err(()) = bar(42).await {}
2294 }
2295 
2296 async fn bar(arg: i32) -> Result<_, ()> {
2297     ${0:todo!()}
2298 }
2299 ",
2300         );
2301     }
2302 
2303     #[test]
create_method()2304     fn create_method() {
2305         check_assist(
2306             generate_function,
2307             r"
2308 struct S;
2309 fn foo() {S.bar$0();}
2310 ",
2311             r"
2312 struct S;
2313 impl S {
2314     fn bar(&self) ${0:-> _} {
2315         todo!()
2316     }
2317 }
2318 fn foo() {S.bar();}
2319 ",
2320         )
2321     }
2322 
2323     #[test]
create_method_within_an_impl()2324     fn create_method_within_an_impl() {
2325         check_assist(
2326             generate_function,
2327             r"
2328 struct S;
2329 fn foo() {S.bar$0();}
2330 impl S {}
2331 
2332 ",
2333             r"
2334 struct S;
2335 fn foo() {S.bar();}
2336 impl S {
2337     fn bar(&self) ${0:-> _} {
2338         todo!()
2339     }
2340 }
2341 
2342 ",
2343         )
2344     }
2345 
2346     #[test]
create_method_from_different_module()2347     fn create_method_from_different_module() {
2348         check_assist(
2349             generate_function,
2350             r"
2351 mod s {
2352     pub struct S;
2353 }
2354 fn foo() {s::S.bar$0();}
2355 ",
2356             r"
2357 mod s {
2358     pub struct S;
2359     impl S {
2360         pub(crate) fn bar(&self) ${0:-> _} {
2361             todo!()
2362         }
2363     }
2364 }
2365 fn foo() {s::S.bar();}
2366 ",
2367         )
2368     }
2369 
2370     #[test]
create_method_from_descendant_module()2371     fn create_method_from_descendant_module() {
2372         check_assist(
2373             generate_function,
2374             r"
2375 struct S;
2376 mod s {
2377     fn foo() {
2378         super::S.bar$0();
2379     }
2380 }
2381 
2382 ",
2383             r"
2384 struct S;
2385 impl S {
2386     fn bar(&self) ${0:-> _} {
2387         todo!()
2388     }
2389 }
2390 mod s {
2391     fn foo() {
2392         super::S.bar();
2393     }
2394 }
2395 
2396 ",
2397         )
2398     }
2399 
2400     #[test]
create_method_with_cursor_anywhere_on_call_expression()2401     fn create_method_with_cursor_anywhere_on_call_expression() {
2402         check_assist(
2403             generate_function,
2404             r"
2405 struct S;
2406 fn foo() {$0S.bar();}
2407 ",
2408             r"
2409 struct S;
2410 impl S {
2411     fn bar(&self) ${0:-> _} {
2412         todo!()
2413     }
2414 }
2415 fn foo() {S.bar();}
2416 ",
2417         )
2418     }
2419 
2420     #[test]
create_async_method()2421     fn create_async_method() {
2422         check_assist(
2423             generate_function,
2424             r"
2425 //- minicore: result
2426 struct S;
2427 async fn foo() {
2428     if let Err(()) = S.$0bar(42).await {}
2429 }
2430 ",
2431             r"
2432 struct S;
2433 impl S {
2434     async fn bar(&self, arg: i32) -> Result<_, ()> {
2435         ${0:todo!()}
2436     }
2437 }
2438 async fn foo() {
2439     if let Err(()) = S.bar(42).await {}
2440 }
2441 ",
2442         )
2443     }
2444 
2445     #[test]
create_static_method()2446     fn create_static_method() {
2447         check_assist(
2448             generate_function,
2449             r"
2450 struct S;
2451 fn foo() {S::bar$0();}
2452 ",
2453             r"
2454 struct S;
2455 impl S {
2456     fn bar() ${0:-> _} {
2457         todo!()
2458     }
2459 }
2460 fn foo() {S::bar();}
2461 ",
2462         )
2463     }
2464 
2465     #[test]
create_async_static_method()2466     fn create_async_static_method() {
2467         check_assist(
2468             generate_function,
2469             r"
2470 //- minicore: result
2471 struct S;
2472 async fn foo() {
2473     if let Err(()) = S::$0bar(42).await {}
2474 }
2475 ",
2476             r"
2477 struct S;
2478 impl S {
2479     async fn bar(arg: i32) -> Result<_, ()> {
2480         ${0:todo!()}
2481     }
2482 }
2483 async fn foo() {
2484     if let Err(()) = S::bar(42).await {}
2485 }
2486 ",
2487         )
2488     }
2489 
2490     #[test]
create_generic_static_method()2491     fn create_generic_static_method() {
2492         check_assist(
2493             generate_function,
2494             r"
2495 struct S;
2496 fn foo<T, const N: usize>(t: [T; N]) { S::bar$0(t); }
2497 ",
2498             r"
2499 struct S;
2500 impl S {
2501     fn bar<T, const N: usize>(t: [T; N]) ${0:-> _} {
2502         todo!()
2503     }
2504 }
2505 fn foo<T, const N: usize>(t: [T; N]) { S::bar(t); }
2506 ",
2507         )
2508     }
2509 
2510     #[test]
create_static_method_within_an_impl()2511     fn create_static_method_within_an_impl() {
2512         check_assist(
2513             generate_function,
2514             r"
2515 struct S;
2516 fn foo() {S::bar$0();}
2517 impl S {}
2518 
2519 ",
2520             r"
2521 struct S;
2522 fn foo() {S::bar();}
2523 impl S {
2524     fn bar() ${0:-> _} {
2525         todo!()
2526     }
2527 }
2528 
2529 ",
2530         )
2531     }
2532 
2533     #[test]
create_static_method_from_different_module()2534     fn create_static_method_from_different_module() {
2535         check_assist(
2536             generate_function,
2537             r"
2538 mod s {
2539     pub struct S;
2540 }
2541 fn foo() {s::S::bar$0();}
2542 ",
2543             r"
2544 mod s {
2545     pub struct S;
2546     impl S {
2547         pub(crate) fn bar() ${0:-> _} {
2548             todo!()
2549         }
2550     }
2551 }
2552 fn foo() {s::S::bar();}
2553 ",
2554         )
2555     }
2556 
2557     #[test]
create_static_method_with_cursor_anywhere_on_call_expression()2558     fn create_static_method_with_cursor_anywhere_on_call_expression() {
2559         check_assist(
2560             generate_function,
2561             r"
2562 struct S;
2563 fn foo() {$0S::bar();}
2564 ",
2565             r"
2566 struct S;
2567 impl S {
2568     fn bar() ${0:-> _} {
2569         todo!()
2570     }
2571 }
2572 fn foo() {S::bar();}
2573 ",
2574         )
2575     }
2576 
2577     #[test]
create_static_method_within_an_impl_with_self_syntax()2578     fn create_static_method_within_an_impl_with_self_syntax() {
2579         check_assist(
2580             generate_function,
2581             r"
2582 struct S;
2583 impl S {
2584     fn foo(&self) {
2585         Self::bar$0();
2586     }
2587 }
2588 ",
2589             r"
2590 struct S;
2591 impl S {
2592     fn foo(&self) {
2593         Self::bar();
2594     }
2595 
2596     fn bar() ${0:-> _} {
2597         todo!()
2598     }
2599 }
2600 ",
2601         )
2602     }
2603 
2604     #[test]
no_panic_on_invalid_global_path()2605     fn no_panic_on_invalid_global_path() {
2606         check_assist(
2607             generate_function,
2608             r"
2609 fn main() {
2610     ::foo$0();
2611 }
2612 ",
2613             r"
2614 fn main() {
2615     ::foo();
2616 }
2617 
2618 fn foo() ${0:-> _} {
2619     todo!()
2620 }
2621 ",
2622         )
2623     }
2624 
2625     #[test]
handle_tuple_indexing()2626     fn handle_tuple_indexing() {
2627         check_assist(
2628             generate_function,
2629             r"
2630 fn main() {
2631     let a = ((),);
2632     foo$0(a.0);
2633 }
2634 ",
2635             r"
2636 fn main() {
2637     let a = ((),);
2638     foo(a.0);
2639 }
2640 
2641 fn foo(a: ()) ${0:-> _} {
2642     todo!()
2643 }
2644 ",
2645         )
2646     }
2647 
2648     #[test]
add_function_with_const_arg()2649     fn add_function_with_const_arg() {
2650         check_assist(
2651             generate_function,
2652             r"
2653 const VALUE: usize = 0;
2654 fn main() {
2655     foo$0(VALUE);
2656 }
2657 ",
2658             r"
2659 const VALUE: usize = 0;
2660 fn main() {
2661     foo(VALUE);
2662 }
2663 
2664 fn foo(value: usize) ${0:-> _} {
2665     todo!()
2666 }
2667 ",
2668         )
2669     }
2670 
2671     #[test]
add_function_with_static_arg()2672     fn add_function_with_static_arg() {
2673         check_assist(
2674             generate_function,
2675             r"
2676 static VALUE: usize = 0;
2677 fn main() {
2678     foo$0(VALUE);
2679 }
2680 ",
2681             r"
2682 static VALUE: usize = 0;
2683 fn main() {
2684     foo(VALUE);
2685 }
2686 
2687 fn foo(value: usize) ${0:-> _} {
2688     todo!()
2689 }
2690 ",
2691         )
2692     }
2693 
2694     #[test]
add_function_with_static_mut_arg()2695     fn add_function_with_static_mut_arg() {
2696         check_assist(
2697             generate_function,
2698             r"
2699 static mut VALUE: usize = 0;
2700 fn main() {
2701     foo$0(VALUE);
2702 }
2703 ",
2704             r"
2705 static mut VALUE: usize = 0;
2706 fn main() {
2707     foo(VALUE);
2708 }
2709 
2710 fn foo(value: usize) ${0:-> _} {
2711     todo!()
2712 }
2713 ",
2714         )
2715     }
2716 
2717     #[test]
not_applicable_for_enum_variant()2718     fn not_applicable_for_enum_variant() {
2719         check_assist_not_applicable(
2720             generate_function,
2721             r"
2722 enum Foo {}
2723 fn main() {
2724     Foo::Bar$0(true)
2725 }
2726 ",
2727         );
2728     }
2729 
2730     #[test]
applicable_for_enum_method()2731     fn applicable_for_enum_method() {
2732         check_assist(
2733             generate_function,
2734             r"
2735 enum Foo {}
2736 fn main() {
2737     Foo::new$0();
2738 }
2739 ",
2740             r"
2741 enum Foo {}
2742 impl Foo {
2743     fn new() ${0:-> _} {
2744         todo!()
2745     }
2746 }
2747 fn main() {
2748     Foo::new();
2749 }
2750 ",
2751         )
2752     }
2753 
2754     #[test]
applicable_in_different_local_crate()2755     fn applicable_in_different_local_crate() {
2756         check_assist(
2757             generate_function,
2758             r"
2759 //- /lib.rs crate:lib new_source_root:local
2760 fn dummy() {}
2761 //- /main.rs crate:main deps:lib new_source_root:local
2762 fn main() {
2763     lib::foo$0();
2764 }
2765 ",
2766             r"
2767 fn dummy() {}
2768 
2769 pub fn foo() ${0:-> _} {
2770     todo!()
2771 }
2772 ",
2773         );
2774     }
2775 
2776     #[test]
applicable_in_different_local_crate_method()2777     fn applicable_in_different_local_crate_method() {
2778         check_assist(
2779             generate_function,
2780             r"
2781 //- /lib.rs crate:lib new_source_root:local
2782 pub struct S;
2783 //- /main.rs crate:main deps:lib new_source_root:local
2784 fn main() {
2785     lib::S.foo$0();
2786 }
2787 ",
2788             r"
2789 pub struct S;
2790 impl S {
2791     pub fn foo(&self) ${0:-> _} {
2792         todo!()
2793     }
2794 }
2795 ",
2796         );
2797     }
2798 
2799     #[test]
not_applicable_in_different_library_crate()2800     fn not_applicable_in_different_library_crate() {
2801         check_assist_not_applicable(
2802             generate_function,
2803             r"
2804 //- /lib.rs crate:lib new_source_root:library
2805 fn dummy() {}
2806 //- /main.rs crate:main deps:lib new_source_root:local
2807 fn main() {
2808     lib::foo$0();
2809 }
2810 ",
2811         );
2812     }
2813 
2814     #[test]
not_applicable_in_different_library_crate_method()2815     fn not_applicable_in_different_library_crate_method() {
2816         check_assist_not_applicable(
2817             generate_function,
2818             r"
2819 //- /lib.rs crate:lib new_source_root:library
2820 pub struct S;
2821 //- /main.rs crate:main deps:lib new_source_root:local
2822 fn main() {
2823     lib::S.foo$0();
2824 }
2825 ",
2826         );
2827     }
2828 }
2829