]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/extract_function.rs
Merge #10645
[rust.git] / crates / ide_assists / src / handlers / extract_function.rs
1 use std::{hash::BuildHasherDefault, iter};
2
3 use ast::make;
4 use either::Either;
5 use hir::{HirDisplay, InFile, Local, ModuleDef, Semantics, TypeInfo};
6 use ide_db::{
7     defs::{Definition, NameRefClass},
8     helpers::{
9         insert_use::{insert_use, ImportScope},
10         mod_path_to_ast,
11         node_ext::{preorder_expr, walk_expr, walk_pat, walk_patterns_in_expr},
12         FamousDefs,
13     },
14     search::{FileReference, ReferenceCategory, SearchScope},
15     RootDatabase,
16 };
17 use itertools::Itertools;
18 use rustc_hash::FxHasher;
19 use stdx::format_to;
20 use syntax::{
21     ast::{
22         self,
23         edit::{AstNodeEdit, IndentLevel},
24         AstNode,
25     },
26     match_ast, ted, SyntaxElement,
27     SyntaxKind::{self, COMMENT},
28     SyntaxNode, SyntaxToken, TextRange, TextSize, TokenAtOffset, WalkEvent, T,
29 };
30
31 use crate::{
32     assist_context::{AssistContext, Assists, TreeMutator},
33     AssistId,
34 };
35
36 type FxIndexSet<T> = indexmap::IndexSet<T, BuildHasherDefault<FxHasher>>;
37
38 // Assist: extract_function
39 //
40 // Extracts selected statements into new function.
41 //
42 // ```
43 // fn main() {
44 //     let n = 1;
45 //     $0let m = n + 2;
46 //     let k = m + n;$0
47 //     let g = 3;
48 // }
49 // ```
50 // ->
51 // ```
52 // fn main() {
53 //     let n = 1;
54 //     fun_name(n);
55 //     let g = 3;
56 // }
57 //
58 // fn $0fun_name(n: i32) {
59 //     let m = n + 2;
60 //     let k = m + n;
61 // }
62 // ```
63 pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
64     let range = ctx.selection_trimmed();
65     if range.is_empty() {
66         return None;
67     }
68
69     let node = ctx.covering_element();
70     if node.kind() == COMMENT {
71         cov_mark::hit!(extract_function_in_comment_is_not_applicable);
72         return None;
73     }
74
75     let node = match node {
76         syntax::NodeOrToken::Node(n) => n,
77         syntax::NodeOrToken::Token(t) => t.parent()?,
78     };
79     let body = extraction_target(&node, range)?;
80     let container_info = body.analyze_container(&ctx.sema)?;
81
82     let (locals_used, self_param) = body.analyze(&ctx.sema);
83
84     let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding };
85     let insert_after = node_to_insert_after(&body, anchor)?;
86     let module = ctx.sema.scope(&insert_after).module()?;
87
88     let ret_ty = body.return_ty(ctx)?;
89     let control_flow = body.external_control_flow(ctx, &container_info)?;
90     let ret_values = body.ret_values(ctx, node.parent().as_ref().unwrap_or(&node));
91
92     let target_range = body.text_range();
93
94     let scope = ImportScope::find_insert_use_container(&node, &ctx.sema)?;
95
96     acc.add(
97         AssistId("extract_function", crate::AssistKind::RefactorExtract),
98         "Extract into function",
99         target_range,
100         move |builder| {
101             let outliving_locals: Vec<_> = ret_values.collect();
102             if stdx::never!(!outliving_locals.is_empty() && !ret_ty.is_unit()) {
103                 // We should not have variables that outlive body if we have expression block
104                 return;
105             }
106
107             let params =
108                 body.extracted_function_params(ctx, &container_info, locals_used.iter().copied());
109
110             let fun = Function {
111                 name: make::name_ref("fun_name"),
112                 self_param,
113                 params,
114                 control_flow,
115                 ret_ty,
116                 body,
117                 outliving_locals,
118                 mods: container_info,
119             };
120
121             let new_indent = IndentLevel::from_node(&insert_after);
122             let old_indent = fun.body.indent_level();
123
124             builder.replace(target_range, make_call(ctx, &fun, old_indent));
125
126             let fn_def = format_function(ctx, module, &fun, old_indent, new_indent);
127             let insert_offset = insert_after.text_range().end();
128
129             if fn_def.contains("ControlFlow") {
130                 let scope = match scope {
131                     ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
132                     ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
133                     ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
134                 };
135
136                 let control_flow_enum =
137                     FamousDefs(&ctx.sema, Some(module.krate())).core_ops_ControlFlow();
138
139                 if let Some(control_flow_enum) = control_flow_enum {
140                     let mod_path = module.find_use_path_prefixed(
141                         ctx.sema.db,
142                         ModuleDef::from(control_flow_enum),
143                         ctx.config.insert_use.prefix_kind,
144                     );
145
146                     if let Some(mod_path) = mod_path {
147                         insert_use(&scope, mod_path_to_ast(&mod_path), &ctx.config.insert_use);
148                     }
149                 }
150             }
151
152             match ctx.config.snippet_cap {
153                 Some(cap) => builder.insert_snippet(cap, insert_offset, fn_def),
154                 None => builder.insert(insert_offset, fn_def),
155             };
156         },
157     )
158 }
159
160 /// Try to guess what user wants to extract
161 ///
162 /// We have basically have two cases:
163 /// * We want whole node, like `loop {}`, `2 + 2`, `{ let n = 1; }` exprs.
164 ///   Then we can use `ast::Expr`
165 /// * We want a few statements for a block. E.g.
166 ///   ```rust,no_run
167 ///   fn foo() -> i32 {
168 ///     let m = 1;
169 ///     $0
170 ///     let n = 2;
171 ///     let k = 3;
172 ///     k + n
173 ///     $0
174 ///   }
175 ///   ```
176 ///
177 fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<FunctionBody> {
178     if let Some(stmt) = ast::Stmt::cast(node.clone()) {
179         return match stmt {
180             ast::Stmt::Item(_) => None,
181             ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => Some(FunctionBody::from_range(
182                 node.parent().and_then(ast::StmtList::cast)?,
183                 node.text_range(),
184             )),
185         };
186     }
187
188     // Covering element returned the parent block of one or multiple statements that have been selected
189     if let Some(stmt_list) = ast::StmtList::cast(node.clone()) {
190         if let Some(block_expr) = stmt_list.syntax().parent().and_then(ast::BlockExpr::cast) {
191             if block_expr.syntax().text_range() == selection_range {
192                 return FunctionBody::from_expr(block_expr.into());
193             }
194         }
195
196         // Extract the full statements.
197         return Some(FunctionBody::from_range(stmt_list, selection_range));
198     }
199
200     let expr = ast::Expr::cast(node.clone())?;
201     // A node got selected fully
202     if node.text_range() == selection_range {
203         return FunctionBody::from_expr(expr);
204     }
205
206     node.ancestors().find_map(ast::Expr::cast).and_then(FunctionBody::from_expr)
207 }
208
209 #[derive(Debug)]
210 struct Function {
211     name: ast::NameRef,
212     self_param: Option<ast::SelfParam>,
213     params: Vec<Param>,
214     control_flow: ControlFlow,
215     ret_ty: RetType,
216     body: FunctionBody,
217     outliving_locals: Vec<OutlivedLocal>,
218     mods: ContainerInfo,
219 }
220
221 #[derive(Debug)]
222 struct Param {
223     var: Local,
224     ty: hir::Type,
225     move_local: bool,
226     requires_mut: bool,
227     is_copy: bool,
228 }
229
230 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
231 enum ParamKind {
232     Value,
233     MutValue,
234     SharedRef,
235     MutRef,
236 }
237
238 #[derive(Debug, Eq, PartialEq)]
239 enum FunType {
240     Unit,
241     Single(hir::Type),
242     Tuple(Vec<hir::Type>),
243 }
244
245 /// Where to put extracted function definition
246 #[derive(Debug)]
247 enum Anchor {
248     /// Extract free function and put right after current top-level function
249     Freestanding,
250     /// Extract method and put right after current function in the impl-block
251     Method,
252 }
253
254 // FIXME: ControlFlow and ContainerInfo both track some function modifiers, feels like these two should
255 // probably be merged somehow.
256 #[derive(Debug)]
257 struct ControlFlow {
258     kind: Option<FlowKind>,
259     is_async: bool,
260     is_unsafe: bool,
261 }
262
263 /// The thing whose expression we are extracting from. Can be a function, const, static, const arg, ...
264 #[derive(Clone, Debug)]
265 struct ContainerInfo {
266     is_const: bool,
267     is_in_tail: bool,
268     parent_loop: Option<SyntaxNode>,
269     /// The function's return type, const's type etc.
270     ret_type: Option<hir::Type>,
271 }
272
273 /// Control flow that is exported from extracted function
274 ///
275 /// E.g.:
276 /// ```rust,no_run
277 /// loop {
278 ///     $0
279 ///     if 42 == 42 {
280 ///         break;
281 ///     }
282 ///     $0
283 /// }
284 /// ```
285 #[derive(Debug, Clone)]
286 enum FlowKind {
287     /// Return with value (`return $expr;`)
288     Return(Option<ast::Expr>),
289     Try {
290         kind: TryKind,
291     },
292     /// Break with value (`break $expr;`)
293     Break(Option<ast::Expr>),
294     /// Continue
295     Continue,
296 }
297
298 #[derive(Debug, Clone)]
299 enum TryKind {
300     Option,
301     Result { ty: hir::Type },
302 }
303
304 #[derive(Debug)]
305 enum RetType {
306     Expr(hir::Type),
307     Stmt,
308 }
309
310 impl RetType {
311     fn is_unit(&self) -> bool {
312         match self {
313             RetType::Expr(ty) => ty.is_unit(),
314             RetType::Stmt => true,
315         }
316     }
317 }
318
319 /// Semantically same as `ast::Expr`, but preserves identity when using only part of the Block
320 /// This is the future function body, the part that is being extracted.
321 #[derive(Debug)]
322 enum FunctionBody {
323     Expr(ast::Expr),
324     Span { parent: ast::StmtList, text_range: TextRange },
325 }
326
327 #[derive(Debug)]
328 struct OutlivedLocal {
329     local: Local,
330     mut_usage_outside_body: bool,
331 }
332
333 /// Container of local variable usages
334 ///
335 /// Semanticall same as `UsageSearchResult`, but provides more convenient interface
336 struct LocalUsages(ide_db::search::UsageSearchResult);
337
338 impl LocalUsages {
339     fn find_local_usages(ctx: &AssistContext, var: Local) -> Self {
340         Self(
341             Definition::Local(var)
342                 .usages(&ctx.sema)
343                 .in_scope(SearchScope::single_file(ctx.file_id()))
344                 .all(),
345         )
346     }
347
348     fn iter(&self) -> impl Iterator<Item = &FileReference> + '_ {
349         self.0.iter().flat_map(|(_, rs)| rs)
350     }
351 }
352
353 impl Function {
354     fn return_type(&self, ctx: &AssistContext) -> FunType {
355         match &self.ret_ty {
356             RetType::Expr(ty) if ty.is_unit() => FunType::Unit,
357             RetType::Expr(ty) => FunType::Single(ty.clone()),
358             RetType::Stmt => match self.outliving_locals.as_slice() {
359                 [] => FunType::Unit,
360                 [var] => FunType::Single(var.local.ty(ctx.db())),
361                 vars => {
362                     let types = vars.iter().map(|v| v.local.ty(ctx.db())).collect();
363                     FunType::Tuple(types)
364                 }
365             },
366         }
367     }
368 }
369
370 impl ParamKind {
371     fn is_ref(&self) -> bool {
372         matches!(self, ParamKind::SharedRef | ParamKind::MutRef)
373     }
374 }
375
376 impl Param {
377     fn kind(&self) -> ParamKind {
378         match (self.move_local, self.requires_mut, self.is_copy) {
379             (false, true, _) => ParamKind::MutRef,
380             (false, false, false) => ParamKind::SharedRef,
381             (true, true, _) => ParamKind::MutValue,
382             (_, false, _) => ParamKind::Value,
383         }
384     }
385
386     fn to_arg(&self, ctx: &AssistContext) -> ast::Expr {
387         let var = path_expr_from_local(ctx, self.var);
388         match self.kind() {
389             ParamKind::Value | ParamKind::MutValue => var,
390             ParamKind::SharedRef => make::expr_ref(var, false),
391             ParamKind::MutRef => make::expr_ref(var, true),
392         }
393     }
394
395     fn to_param(&self, ctx: &AssistContext, module: hir::Module) -> ast::Param {
396         let var = self.var.name(ctx.db()).unwrap().to_string();
397         let var_name = make::name(&var);
398         let pat = match self.kind() {
399             ParamKind::MutValue => make::ident_pat(false, true, var_name),
400             ParamKind::Value | ParamKind::SharedRef | ParamKind::MutRef => {
401                 make::ext::simple_ident_pat(var_name)
402             }
403         };
404
405         let ty = make_ty(&self.ty, ctx, module);
406         let ty = match self.kind() {
407             ParamKind::Value | ParamKind::MutValue => ty,
408             ParamKind::SharedRef => make::ty_ref(ty, false),
409             ParamKind::MutRef => make::ty_ref(ty, true),
410         };
411
412         make::param(pat.into(), ty)
413     }
414 }
415
416 impl TryKind {
417     fn of_ty(ty: hir::Type, ctx: &AssistContext) -> Option<TryKind> {
418         if ty.is_unknown() {
419             // We favour Result for `expr?`
420             return Some(TryKind::Result { ty });
421         }
422         let adt = ty.as_adt()?;
423         let name = adt.name(ctx.db());
424         // FIXME: use lang items to determine if it is std type or user defined
425         //        E.g. if user happens to define type named `Option`, we would have false positive
426         match name.to_string().as_str() {
427             "Option" => Some(TryKind::Option),
428             "Result" => Some(TryKind::Result { ty }),
429             _ => None,
430         }
431     }
432 }
433
434 impl FlowKind {
435     fn make_result_handler(&self, expr: Option<ast::Expr>) -> ast::Expr {
436         match self {
437             FlowKind::Return(_) => make::expr_return(expr),
438             FlowKind::Break(_) => make::expr_break(expr),
439             FlowKind::Try { .. } => {
440                 stdx::never!("cannot have result handler with try");
441                 expr.unwrap_or_else(|| make::expr_return(None))
442             }
443             FlowKind::Continue => {
444                 stdx::always!(expr.is_none(), "continue with value is not possible");
445                 make::expr_continue()
446             }
447         }
448     }
449
450     fn expr_ty(&self, ctx: &AssistContext) -> Option<hir::Type> {
451         match self {
452             FlowKind::Return(Some(expr)) | FlowKind::Break(Some(expr)) => {
453                 ctx.sema.type_of_expr(expr).map(TypeInfo::adjusted)
454             }
455             FlowKind::Try { .. } => {
456                 stdx::never!("try does not have defined expr_ty");
457                 None
458             }
459             _ => None,
460         }
461     }
462 }
463
464 impl FunctionBody {
465     fn parent(&self) -> Option<SyntaxNode> {
466         match self {
467             FunctionBody::Expr(expr) => expr.syntax().parent(),
468             FunctionBody::Span { parent, .. } => Some(parent.syntax().clone()),
469         }
470     }
471
472     fn from_expr(expr: ast::Expr) -> Option<Self> {
473         match expr {
474             ast::Expr::BreakExpr(it) => it.expr().map(Self::Expr),
475             ast::Expr::ReturnExpr(it) => it.expr().map(Self::Expr),
476             ast::Expr::BlockExpr(it) if !it.is_standalone() => None,
477             expr => Some(Self::Expr(expr)),
478         }
479     }
480
481     fn from_range(parent: ast::StmtList, selected: TextRange) -> FunctionBody {
482         let mut text_range = parent
483             .statements()
484             .map(|stmt| stmt.syntax().text_range())
485             .filter(|&stmt| selected.intersect(stmt).filter(|it| !it.is_empty()).is_some())
486             .fold1(|acc, stmt| acc.cover(stmt));
487         if let Some(tail_range) = parent
488             .tail_expr()
489             .map(|it| it.syntax().text_range())
490             .filter(|&it| selected.intersect(it).is_some())
491         {
492             text_range = Some(match text_range {
493                 Some(text_range) => text_range.cover(tail_range),
494                 None => tail_range,
495             });
496         }
497         Self::Span { parent, text_range: text_range.unwrap_or(selected) }
498     }
499
500     fn indent_level(&self) -> IndentLevel {
501         match &self {
502             FunctionBody::Expr(expr) => IndentLevel::from_node(expr.syntax()),
503             FunctionBody::Span { parent, .. } => IndentLevel::from_node(parent.syntax()) + 1,
504         }
505     }
506
507     fn tail_expr(&self) -> Option<ast::Expr> {
508         match &self {
509             FunctionBody::Expr(expr) => Some(expr.clone()),
510             FunctionBody::Span { parent, text_range } => {
511                 let tail_expr = parent.tail_expr()?;
512                 text_range.contains_range(tail_expr.syntax().text_range()).then(|| tail_expr)
513             }
514         }
515     }
516
517     fn walk_expr(&self, cb: &mut dyn FnMut(ast::Expr)) {
518         match self {
519             FunctionBody::Expr(expr) => walk_expr(expr, cb),
520             FunctionBody::Span { parent, text_range } => {
521                 parent
522                     .statements()
523                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
524                     .filter_map(|stmt| match stmt {
525                         ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(),
526                         ast::Stmt::Item(_) => None,
527                         ast::Stmt::LetStmt(stmt) => stmt.initializer(),
528                     })
529                     .for_each(|expr| walk_expr(&expr, cb));
530                 if let Some(expr) = parent
531                     .tail_expr()
532                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
533                 {
534                     walk_expr(&expr, cb);
535                 }
536             }
537         }
538     }
539
540     fn preorder_expr(&self, cb: &mut dyn FnMut(WalkEvent<ast::Expr>) -> bool) {
541         match self {
542             FunctionBody::Expr(expr) => preorder_expr(expr, cb),
543             FunctionBody::Span { parent, text_range } => {
544                 parent
545                     .statements()
546                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
547                     .filter_map(|stmt| match stmt {
548                         ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr(),
549                         ast::Stmt::Item(_) => None,
550                         ast::Stmt::LetStmt(stmt) => stmt.initializer(),
551                     })
552                     .for_each(|expr| preorder_expr(&expr, cb));
553                 if let Some(expr) = parent
554                     .tail_expr()
555                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
556                 {
557                     preorder_expr(&expr, cb);
558                 }
559             }
560         }
561     }
562
563     fn walk_pat(&self, cb: &mut dyn FnMut(ast::Pat)) {
564         match self {
565             FunctionBody::Expr(expr) => walk_patterns_in_expr(expr, cb),
566             FunctionBody::Span { parent, text_range } => {
567                 parent
568                     .statements()
569                     .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
570                     .for_each(|stmt| match stmt {
571                         ast::Stmt::ExprStmt(expr_stmt) => {
572                             if let Some(expr) = expr_stmt.expr() {
573                                 walk_patterns_in_expr(&expr, cb)
574                             }
575                         }
576                         ast::Stmt::Item(_) => (),
577                         ast::Stmt::LetStmt(stmt) => {
578                             if let Some(pat) = stmt.pat() {
579                                 walk_pat(&pat, cb);
580                             }
581                             if let Some(expr) = stmt.initializer() {
582                                 walk_patterns_in_expr(&expr, cb);
583                             }
584                         }
585                     });
586                 if let Some(expr) = parent
587                     .tail_expr()
588                     .filter(|it| text_range.contains_range(it.syntax().text_range()))
589                 {
590                     walk_patterns_in_expr(&expr, cb);
591                 }
592             }
593         }
594     }
595
596     fn text_range(&self) -> TextRange {
597         match self {
598             FunctionBody::Expr(expr) => expr.syntax().text_range(),
599             &FunctionBody::Span { text_range, .. } => text_range,
600         }
601     }
602
603     fn contains_range(&self, range: TextRange) -> bool {
604         self.text_range().contains_range(range)
605     }
606
607     fn precedes_range(&self, range: TextRange) -> bool {
608         self.text_range().end() <= range.start()
609     }
610
611     fn contains_node(&self, node: &SyntaxNode) -> bool {
612         self.contains_range(node.text_range())
613     }
614 }
615
616 impl FunctionBody {
617     /// Analyzes a function body, returning the used local variables that are referenced in it as well as
618     /// whether it contains an await expression.
619     fn analyze(
620         &self,
621         sema: &Semantics<RootDatabase>,
622     ) -> (FxIndexSet<Local>, Option<ast::SelfParam>) {
623         let mut self_param = None;
624         let mut res = FxIndexSet::default();
625         let mut cb = |name_ref: Option<_>| {
626             let local_ref =
627                 match name_ref.and_then(|name_ref| NameRefClass::classify(sema, &name_ref)) {
628                     Some(
629                         NameRefClass::Definition(Definition::Local(local_ref))
630                         | NameRefClass::FieldShorthand { local_ref, field_ref: _ },
631                     ) => local_ref,
632                     _ => return,
633                 };
634             let InFile { file_id, value } = local_ref.source(sema.db);
635             // locals defined inside macros are not relevant to us
636             if !file_id.is_macro() {
637                 match value {
638                     Either::Right(it) => {
639                         self_param.replace(it);
640                     }
641                     Either::Left(_) => {
642                         res.insert(local_ref);
643                     }
644                 }
645             }
646         };
647         self.walk_expr(&mut |expr| match expr {
648             ast::Expr::PathExpr(path_expr) => {
649                 cb(path_expr.path().and_then(|it| it.as_single_name_ref()))
650             }
651             ast::Expr::MacroCall(call) => {
652                 if let Some(tt) = call.token_tree() {
653                     tt.syntax()
654                         .children_with_tokens()
655                         .flat_map(SyntaxElement::into_token)
656                         .filter(|it| it.kind() == SyntaxKind::IDENT)
657                         .flat_map(|t| sema.descend_into_macros(t))
658                         .for_each(|t| cb(t.parent().and_then(ast::NameRef::cast)));
659                 }
660             }
661             _ => (),
662         });
663         (res, self_param)
664     }
665
666     fn analyze_container(&self, sema: &Semantics<RootDatabase>) -> Option<ContainerInfo> {
667         let mut ancestors = self.parent()?.ancestors();
668         let infer_expr_opt = |expr| sema.type_of_expr(&expr?).map(TypeInfo::adjusted);
669         let mut parent_loop = None;
670         let mut set_parent_loop = |loop_: &dyn ast::HasLoopBody| {
671             if loop_
672                 .loop_body()
673                 .map_or(false, |it| it.syntax().text_range().contains_range(self.text_range()))
674             {
675                 parent_loop.get_or_insert(loop_.syntax().clone());
676             }
677         };
678         let (is_const, expr, ty) = loop {
679             let anc = ancestors.next()?;
680             break match_ast! {
681                 match anc {
682                     ast::ClosureExpr(closure) => (false, closure.body(), infer_expr_opt(closure.body())),
683                     ast::BlockExpr(block_expr) => {
684                         let (constness, block) = match block_expr.modifier() {
685                             Some(ast::BlockModifier::Const(_)) => (true, block_expr),
686                             Some(ast::BlockModifier::Try(_)) => (false, block_expr),
687                             Some(ast::BlockModifier::Label(label)) if label.lifetime().is_some() => (false, block_expr),
688                             _ => continue,
689                         };
690                         let expr = Some(ast::Expr::BlockExpr(block));
691                         (constness, expr.clone(), infer_expr_opt(expr))
692                     },
693                     ast::Fn(fn_) => {
694                         (fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(sema.to_def(&fn_)?.ret_type(sema.db)))
695                     },
696                     ast::Static(statik) => {
697                         (true, statik.body(), Some(sema.to_def(&statik)?.ty(sema.db)))
698                     },
699                     ast::ConstArg(ca) => {
700                         (true, ca.expr(), infer_expr_opt(ca.expr()))
701                     },
702                     ast::Const(konst) => {
703                         (true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db)))
704                     },
705                     ast::ConstParam(cp) => {
706                         (true, cp.default_val(), Some(sema.to_def(&cp)?.ty(sema.db)))
707                     },
708                     ast::ConstBlockPat(cbp) => {
709                         let expr = cbp.block_expr().map(ast::Expr::BlockExpr);
710                         (true, expr.clone(), infer_expr_opt(expr))
711                     },
712                     ast::Variant(__) => return None,
713                     ast::Meta(__) => return None,
714                     ast::LoopExpr(it) => {
715                         set_parent_loop(&it);
716                         continue;
717                     },
718                     ast::ForExpr(it) => {
719                         set_parent_loop(&it);
720                         continue;
721                     },
722                     ast::WhileExpr(it) => {
723                         set_parent_loop(&it);
724                         continue;
725                     },
726                     _ => continue,
727                 }
728             };
729         };
730         let container_tail = match expr? {
731             ast::Expr::BlockExpr(block) => block.tail_expr(),
732             expr => Some(expr),
733         };
734         let is_in_tail =
735             container_tail.zip(self.tail_expr()).map_or(false, |(container_tail, body_tail)| {
736                 container_tail.syntax().text_range().contains_range(body_tail.syntax().text_range())
737             });
738         Some(ContainerInfo { is_in_tail, is_const, parent_loop, ret_type: ty })
739     }
740
741     fn return_ty(&self, ctx: &AssistContext) -> Option<RetType> {
742         match self.tail_expr() {
743             Some(expr) => ctx.sema.type_of_expr(&expr).map(TypeInfo::original).map(RetType::Expr),
744             None => Some(RetType::Stmt),
745         }
746     }
747
748     /// Local variables defined inside `body` that are accessed outside of it
749     fn ret_values<'a>(
750         &self,
751         ctx: &'a AssistContext,
752         parent: &SyntaxNode,
753     ) -> impl Iterator<Item = OutlivedLocal> + 'a {
754         let parent = parent.clone();
755         let range = self.text_range();
756         locals_defined_in_body(&ctx.sema, self)
757             .into_iter()
758             .filter_map(move |local| local_outlives_body(ctx, range, local, &parent))
759     }
760
761     /// Analyses the function body for external control flow.
762     fn external_control_flow(
763         &self,
764         ctx: &AssistContext,
765         container_info: &ContainerInfo,
766     ) -> Option<ControlFlow> {
767         let mut ret_expr = None;
768         let mut try_expr = None;
769         let mut break_expr = None;
770         let mut continue_expr = None;
771         let mut is_async = false;
772         let mut _is_unsafe = false;
773
774         let mut unsafe_depth = 0;
775         let mut loop_depth = 0;
776
777         self.preorder_expr(&mut |expr| {
778             let expr = match expr {
779                 WalkEvent::Enter(e) => e,
780                 WalkEvent::Leave(expr) => {
781                     match expr {
782                         ast::Expr::LoopExpr(_)
783                         | ast::Expr::ForExpr(_)
784                         | ast::Expr::WhileExpr(_) => loop_depth -= 1,
785                         ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
786                             unsafe_depth -= 1
787                         }
788                         _ => (),
789                     }
790                     return false;
791                 }
792             };
793             match expr {
794                 ast::Expr::LoopExpr(_) | ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) => {
795                     loop_depth += 1;
796                 }
797                 ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
798                     unsafe_depth += 1
799                 }
800                 ast::Expr::ReturnExpr(it) => {
801                     ret_expr = Some(it);
802                 }
803                 ast::Expr::TryExpr(it) => {
804                     try_expr = Some(it);
805                 }
806                 ast::Expr::BreakExpr(it) if loop_depth == 0 => {
807                     break_expr = Some(it);
808                 }
809                 ast::Expr::ContinueExpr(it) if loop_depth == 0 => {
810                     continue_expr = Some(it);
811                 }
812                 ast::Expr::AwaitExpr(_) => is_async = true,
813                 // FIXME: Do unsafe analysis on expression, sem highlighting knows this so we should be able
814                 // to just lift that out of there
815                 // expr if unsafe_depth ==0 && expr.is_unsafe => is_unsafe = true,
816                 _ => {}
817             }
818             false
819         });
820
821         let kind = match (try_expr, ret_expr, break_expr, continue_expr) {
822             (Some(_), _, None, None) => {
823                 let ret_ty = container_info.ret_type.clone()?;
824                 let kind = TryKind::of_ty(ret_ty, ctx)?;
825
826                 Some(FlowKind::Try { kind })
827             }
828             (Some(_), _, _, _) => {
829                 cov_mark::hit!(external_control_flow_try_and_bc);
830                 return None;
831             }
832             (None, Some(r), None, None) => Some(FlowKind::Return(r.expr())),
833             (None, Some(_), _, _) => {
834                 cov_mark::hit!(external_control_flow_return_and_bc);
835                 return None;
836             }
837             (None, None, Some(_), Some(_)) => {
838                 cov_mark::hit!(external_control_flow_break_and_continue);
839                 return None;
840             }
841             (None, None, Some(b), None) => Some(FlowKind::Break(b.expr())),
842             (None, None, None, Some(_)) => Some(FlowKind::Continue),
843             (None, None, None, None) => None,
844         };
845
846         Some(ControlFlow { kind, is_async, is_unsafe: _is_unsafe })
847     }
848
849     /// find variables that should be extracted as params
850     ///
851     /// Computes additional info that affects param type and mutability
852     fn extracted_function_params(
853         &self,
854         ctx: &AssistContext,
855         container_info: &ContainerInfo,
856         locals: impl Iterator<Item = Local>,
857     ) -> Vec<Param> {
858         locals
859             .map(|local| (local, local.source(ctx.db())))
860             .filter(|(_, src)| is_defined_outside_of_body(ctx, self, src))
861             .filter_map(|(local, src)| match src.value {
862                 Either::Left(src) => Some((local, src)),
863                 Either::Right(_) => {
864                     stdx::never!(false, "Local::is_self returned false, but source is SelfParam");
865                     None
866                 }
867             })
868             .map(|(var, src)| {
869                 let usages = LocalUsages::find_local_usages(ctx, var);
870                 let ty = var.ty(ctx.db());
871
872                 let defined_outside_parent_loop = container_info
873                     .parent_loop
874                     .as_ref()
875                     .map_or(true, |it| it.text_range().contains_range(src.syntax().text_range()));
876
877                 let is_copy = ty.is_copy(ctx.db());
878                 let has_usages = self.has_usages_after_body(&usages);
879                 let requires_mut =
880                     !ty.is_mutable_reference() && has_exclusive_usages(ctx, &usages, self);
881                 // We can move the value into the function call if it's not used after the call,
882                 // if the var is not used but defined outside a loop we are extracting from we can't move it either
883                 // as the function will reuse it in the next iteration.
884                 let move_local = !has_usages && defined_outside_parent_loop;
885                 Param { var, ty, move_local, requires_mut, is_copy }
886             })
887             .collect()
888     }
889
890     fn has_usages_after_body(&self, usages: &LocalUsages) -> bool {
891         usages.iter().any(|reference| self.precedes_range(reference.range))
892     }
893 }
894
895 /// checks if relevant var is used with `&mut` access inside body
896 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
897     usages
898         .iter()
899         .filter(|reference| body.contains_range(reference.range))
900         .any(|reference| reference_is_exclusive(reference, body, ctx))
901 }
902
903 /// checks if this reference requires `&mut` access inside node
904 fn reference_is_exclusive(
905     reference: &FileReference,
906     node: &dyn HasTokenAtOffset,
907     ctx: &AssistContext,
908 ) -> bool {
909     // we directly modify variable with set: `n = 0`, `n += 1`
910     if reference.category == Some(ReferenceCategory::Write) {
911         return true;
912     }
913
914     // we take `&mut` reference to variable: `&mut v`
915     let path = match path_element_of_reference(node, reference) {
916         Some(path) => path,
917         None => return false,
918     };
919
920     expr_require_exclusive_access(ctx, &path).unwrap_or(false)
921 }
922
923 /// checks if this expr requires `&mut` access, recurses on field access
924 fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
925     if let ast::Expr::MacroCall(_) = expr {
926         // FIXME: expand macro and check output for mutable usages of the variable?
927         return None;
928     }
929
930     let parent = expr.syntax().parent()?;
931
932     if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
933         if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
934             return Some(bin_expr.lhs()?.syntax() == expr.syntax());
935         }
936         return Some(false);
937     }
938
939     if let Some(ref_expr) = ast::RefExpr::cast(parent.clone()) {
940         return Some(ref_expr.mut_token().is_some());
941     }
942
943     if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
944         let func = ctx.sema.resolve_method_call(&method_call)?;
945         let self_param = func.self_param(ctx.db())?;
946         let access = self_param.access(ctx.db());
947
948         return Some(matches!(access, hir::Access::Exclusive));
949     }
950
951     if let Some(field) = ast::FieldExpr::cast(parent) {
952         return expr_require_exclusive_access(ctx, &field.into());
953     }
954
955     Some(false)
956 }
957
958 trait HasTokenAtOffset {
959     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken>;
960 }
961
962 impl HasTokenAtOffset for SyntaxNode {
963     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
964         SyntaxNode::token_at_offset(self, offset)
965     }
966 }
967
968 impl HasTokenAtOffset for FunctionBody {
969     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
970         match self {
971             FunctionBody::Expr(expr) => expr.syntax().token_at_offset(offset),
972             FunctionBody::Span { parent, text_range } => {
973                 match parent.syntax().token_at_offset(offset) {
974                     TokenAtOffset::None => TokenAtOffset::None,
975                     TokenAtOffset::Single(t) => {
976                         if text_range.contains_range(t.text_range()) {
977                             TokenAtOffset::Single(t)
978                         } else {
979                             TokenAtOffset::None
980                         }
981                     }
982                     TokenAtOffset::Between(a, b) => {
983                         match (
984                             text_range.contains_range(a.text_range()),
985                             text_range.contains_range(b.text_range()),
986                         ) {
987                             (true, true) => TokenAtOffset::Between(a, b),
988                             (true, false) => TokenAtOffset::Single(a),
989                             (false, true) => TokenAtOffset::Single(b),
990                             (false, false) => TokenAtOffset::None,
991                         }
992                     }
993                 }
994             }
995         }
996     }
997 }
998
999 /// find relevant `ast::Expr` for reference
1000 ///
1001 /// # Preconditions
1002 ///
1003 /// `node` must cover `reference`, that is `node.text_range().contains_range(reference.range)`
1004 fn path_element_of_reference(
1005     node: &dyn HasTokenAtOffset,
1006     reference: &FileReference,
1007 ) -> Option<ast::Expr> {
1008     let token = node.token_at_offset(reference.range.start()).right_biased().or_else(|| {
1009         stdx::never!(false, "cannot find token at variable usage: {:?}", reference);
1010         None
1011     })?;
1012     let path = token.ancestors().find_map(ast::Expr::cast).or_else(|| {
1013         stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
1014         None
1015     })?;
1016     stdx::always!(
1017         matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
1018         "unexpected expression type for variable usage: {:?}",
1019         path
1020     );
1021     Some(path)
1022 }
1023
1024 /// list local variables defined inside `body`
1025 fn locals_defined_in_body(
1026     sema: &Semantics<RootDatabase>,
1027     body: &FunctionBody,
1028 ) -> FxIndexSet<Local> {
1029     // FIXME: this doesn't work well with macros
1030     //        see https://github.com/rust-analyzer/rust-analyzer/pull/7535#discussion_r570048550
1031     let mut res = FxIndexSet::default();
1032     body.walk_pat(&mut |pat| {
1033         if let ast::Pat::IdentPat(pat) = pat {
1034             if let Some(local) = sema.to_def(&pat) {
1035                 res.insert(local);
1036             }
1037         }
1038     });
1039     res
1040 }
1041
1042 /// Returns usage details if local variable is used after(outside of) body
1043 fn local_outlives_body(
1044     ctx: &AssistContext,
1045     body_range: TextRange,
1046     local: Local,
1047     parent: &SyntaxNode,
1048 ) -> Option<OutlivedLocal> {
1049     let usages = LocalUsages::find_local_usages(ctx, local);
1050     let mut has_mut_usages = false;
1051     let mut any_outlives = false;
1052     for usage in usages.iter() {
1053         if body_range.end() <= usage.range.start() {
1054             has_mut_usages |= reference_is_exclusive(usage, parent, ctx);
1055             any_outlives |= true;
1056             if has_mut_usages {
1057                 break; // no need to check more elements we have all the info we wanted
1058             }
1059         }
1060     }
1061     if !any_outlives {
1062         return None;
1063     }
1064     Some(OutlivedLocal { local, mut_usage_outside_body: has_mut_usages })
1065 }
1066
1067 /// checks if the relevant local was defined before(outside of) body
1068 fn is_defined_outside_of_body(
1069     ctx: &AssistContext,
1070     body: &FunctionBody,
1071     src: &hir::InFile<Either<ast::IdentPat, ast::SelfParam>>,
1072 ) -> bool {
1073     src.file_id.original_file(ctx.db()) == ctx.file_id()
1074         && !body.contains_node(either_syntax(&src.value))
1075 }
1076
1077 fn either_syntax(value: &Either<ast::IdentPat, ast::SelfParam>) -> &SyntaxNode {
1078     match value {
1079         Either::Left(pat) => pat.syntax(),
1080         Either::Right(it) => it.syntax(),
1081     }
1082 }
1083
1084 /// find where to put extracted function definition
1085 ///
1086 /// Function should be put right after returned node
1087 fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNode> {
1088     let node = match body {
1089         FunctionBody::Expr(e) => e.syntax(),
1090         FunctionBody::Span { parent, .. } => parent.syntax(),
1091     };
1092     let mut ancestors = node.ancestors().peekable();
1093     let mut last_ancestor = None;
1094     while let Some(next_ancestor) = ancestors.next() {
1095         match next_ancestor.kind() {
1096             SyntaxKind::SOURCE_FILE => break,
1097             SyntaxKind::ITEM_LIST if !matches!(anchor, Anchor::Freestanding) => continue,
1098             SyntaxKind::ITEM_LIST => {
1099                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
1100                     break;
1101                 }
1102             }
1103             SyntaxKind::ASSOC_ITEM_LIST if !matches!(anchor, Anchor::Method) => {
1104                 continue;
1105             }
1106             SyntaxKind::ASSOC_ITEM_LIST => {
1107                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::IMPL) {
1108                     break;
1109                 }
1110             }
1111             _ => (),
1112         }
1113         last_ancestor = Some(next_ancestor);
1114     }
1115     last_ancestor
1116 }
1117
1118 fn make_call(ctx: &AssistContext, fun: &Function, indent: IndentLevel) -> String {
1119     let ret_ty = fun.return_type(ctx);
1120
1121     let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx)));
1122     let name = fun.name.clone();
1123     let mut call_expr = if fun.self_param.is_some() {
1124         let self_arg = make::expr_path(make::ext::ident_path("self"));
1125         make::expr_method_call(self_arg, name, args)
1126     } else {
1127         let func = make::expr_path(make::path_unqualified(make::path_segment(name)));
1128         make::expr_call(func, args)
1129     };
1130
1131     let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1132
1133     if fun.control_flow.is_async {
1134         call_expr = make::expr_await(call_expr);
1135     }
1136     let expr = handler.make_call_expr(call_expr).indent(indent);
1137
1138     let mut_modifier = |var: &OutlivedLocal| if var.mut_usage_outside_body { "mut " } else { "" };
1139
1140     let mut buf = String::new();
1141     match fun.outliving_locals.as_slice() {
1142         [] => {}
1143         [var] => {
1144             format_to!(buf, "let {}{} = ", mut_modifier(var), var.local.name(ctx.db()).unwrap())
1145         }
1146         vars => {
1147             buf.push_str("let (");
1148             let bindings = vars.iter().format_with(", ", |local, f| {
1149                 f(&format_args!("{}{}", mut_modifier(local), local.local.name(ctx.db()).unwrap()))
1150             });
1151             format_to!(buf, "{}", bindings);
1152             buf.push_str(") = ");
1153         }
1154     }
1155
1156     format_to!(buf, "{}", expr);
1157     let insert_comma = fun
1158         .body
1159         .parent()
1160         .and_then(ast::MatchArm::cast)
1161         .map_or(false, |it| it.comma_token().is_none());
1162     if insert_comma {
1163         buf.push(',');
1164     } else if fun.ret_ty.is_unit() && (!fun.outliving_locals.is_empty() || !expr.is_block_like()) {
1165         buf.push(';');
1166     }
1167     buf
1168 }
1169
1170 enum FlowHandler {
1171     None,
1172     Try { kind: TryKind },
1173     If { action: FlowKind },
1174     IfOption { action: FlowKind },
1175     MatchOption { none: FlowKind },
1176     MatchResult { err: FlowKind },
1177 }
1178
1179 impl FlowHandler {
1180     fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
1181         match &fun.control_flow.kind {
1182             None => FlowHandler::None,
1183             Some(flow_kind) => {
1184                 let action = flow_kind.clone();
1185                 if *ret_ty == FunType::Unit {
1186                     match flow_kind {
1187                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1188                             FlowHandler::If { action }
1189                         }
1190                         FlowKind::Return(_) | FlowKind::Break(_) => {
1191                             FlowHandler::IfOption { action }
1192                         }
1193                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1194                     }
1195                 } else {
1196                     match flow_kind {
1197                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1198                             FlowHandler::MatchOption { none: action }
1199                         }
1200                         FlowKind::Return(_) | FlowKind::Break(_) => {
1201                             FlowHandler::MatchResult { err: action }
1202                         }
1203                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1204                     }
1205                 }
1206             }
1207         }
1208     }
1209
1210     fn make_call_expr(&self, call_expr: ast::Expr) -> ast::Expr {
1211         match self {
1212             FlowHandler::None => call_expr,
1213             FlowHandler::Try { kind: _ } => make::expr_try(call_expr),
1214             FlowHandler::If { action } => {
1215                 let action = action.make_result_handler(None);
1216                 let stmt = make::expr_stmt(action);
1217                 let block = make::block_expr(iter::once(stmt.into()), None);
1218                 let controlflow_break_path = make::path_from_text("ControlFlow::Break");
1219                 let condition = make::condition(
1220                     call_expr,
1221                     Some(
1222                         make::tuple_struct_pat(
1223                             controlflow_break_path,
1224                             iter::once(make::wildcard_pat().into()),
1225                         )
1226                         .into(),
1227                     ),
1228                 );
1229                 make::expr_if(condition, block, None)
1230             }
1231             FlowHandler::IfOption { action } => {
1232                 let path = make::ext::ident_path("Some");
1233                 let value_pat = make::ext::simple_ident_pat(make::name("value"));
1234                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1235                 let cond = make::condition(call_expr, Some(pattern.into()));
1236                 let value = make::expr_path(make::ext::ident_path("value"));
1237                 let action_expr = action.make_result_handler(Some(value));
1238                 let action_stmt = make::expr_stmt(action_expr);
1239                 let then = make::block_expr(iter::once(action_stmt.into()), None);
1240                 make::expr_if(cond, then, None)
1241             }
1242             FlowHandler::MatchOption { none } => {
1243                 let some_name = "value";
1244
1245                 let some_arm = {
1246                     let path = make::ext::ident_path("Some");
1247                     let value_pat = make::ext::simple_ident_pat(make::name(some_name));
1248                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1249                     let value = make::expr_path(make::ext::ident_path(some_name));
1250                     make::match_arm(iter::once(pat.into()), None, value)
1251                 };
1252                 let none_arm = {
1253                     let path = make::ext::ident_path("None");
1254                     let pat = make::path_pat(path);
1255                     make::match_arm(iter::once(pat), None, none.make_result_handler(None))
1256                 };
1257                 let arms = make::match_arm_list(vec![some_arm, none_arm]);
1258                 make::expr_match(call_expr, arms)
1259             }
1260             FlowHandler::MatchResult { err } => {
1261                 let ok_name = "value";
1262                 let err_name = "value";
1263
1264                 let ok_arm = {
1265                     let path = make::ext::ident_path("Ok");
1266                     let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
1267                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1268                     let value = make::expr_path(make::ext::ident_path(ok_name));
1269                     make::match_arm(iter::once(pat.into()), None, value)
1270                 };
1271                 let err_arm = {
1272                     let path = make::ext::ident_path("Err");
1273                     let value_pat = make::ext::simple_ident_pat(make::name(err_name));
1274                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1275                     let value = make::expr_path(make::ext::ident_path(err_name));
1276                     make::match_arm(
1277                         iter::once(pat.into()),
1278                         None,
1279                         err.make_result_handler(Some(value)),
1280                     )
1281                 };
1282                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1283                 make::expr_match(call_expr, arms)
1284             }
1285         }
1286     }
1287 }
1288
1289 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1290     let name = var.name(ctx.db()).unwrap().to_string();
1291     make::expr_path(make::ext::ident_path(&name))
1292 }
1293
1294 fn format_function(
1295     ctx: &AssistContext,
1296     module: hir::Module,
1297     fun: &Function,
1298     old_indent: IndentLevel,
1299     new_indent: IndentLevel,
1300 ) -> String {
1301     let mut fn_def = String::new();
1302     let params = fun.make_param_list(ctx, module);
1303     let ret_ty = fun.make_ret_ty(ctx, module);
1304     let body = make_body(ctx, old_indent, new_indent, fun);
1305     let const_kw = if fun.mods.is_const { "const " } else { "" };
1306     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
1307     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
1308     match ctx.config.snippet_cap {
1309         Some(_) => format_to!(
1310             fn_def,
1311             "\n\n{}{}{}{}fn $0{}{}",
1312             new_indent,
1313             const_kw,
1314             async_kw,
1315             unsafe_kw,
1316             fun.name,
1317             params
1318         ),
1319         None => format_to!(
1320             fn_def,
1321             "\n\n{}{}{}{}fn {}{}",
1322             new_indent,
1323             const_kw,
1324             async_kw,
1325             unsafe_kw,
1326             fun.name,
1327             params
1328         ),
1329     }
1330     if let Some(ret_ty) = ret_ty {
1331         format_to!(fn_def, " {}", ret_ty);
1332     }
1333     format_to!(fn_def, " {}", body);
1334
1335     fn_def
1336 }
1337
1338 impl Function {
1339     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
1340         let self_param = self.self_param.clone();
1341         let params = self.params.iter().map(|param| param.to_param(ctx, module));
1342         make::param_list(self_param, params)
1343     }
1344
1345     fn make_ret_ty(&self, ctx: &AssistContext, module: hir::Module) -> Option<ast::RetType> {
1346         let fun_ty = self.return_type(ctx);
1347         let handler = if self.mods.is_in_tail {
1348             FlowHandler::None
1349         } else {
1350             FlowHandler::from_ret_ty(self, &fun_ty)
1351         };
1352         let ret_ty = match &handler {
1353             FlowHandler::None => {
1354                 if matches!(fun_ty, FunType::Unit) {
1355                     return None;
1356                 }
1357                 fun_ty.make_ty(ctx, module)
1358             }
1359             FlowHandler::Try { kind: TryKind::Option } => {
1360                 make::ext::ty_option(fun_ty.make_ty(ctx, module))
1361             }
1362             FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1363                 let handler_ty = parent_ret_ty
1364                     .type_arguments()
1365                     .nth(1)
1366                     .map(|ty| make_ty(&ty, ctx, module))
1367                     .unwrap_or_else(make::ty_placeholder);
1368                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1369             }
1370             FlowHandler::If { .. } => make::ty("ControlFlow<()>"),
1371             FlowHandler::IfOption { action } => {
1372                 let handler_ty = action
1373                     .expr_ty(ctx)
1374                     .map(|ty| make_ty(&ty, ctx, module))
1375                     .unwrap_or_else(make::ty_placeholder);
1376                 make::ext::ty_option(handler_ty)
1377             }
1378             FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1379             FlowHandler::MatchResult { err } => {
1380                 let handler_ty = err
1381                     .expr_ty(ctx)
1382                     .map(|ty| make_ty(&ty, ctx, module))
1383                     .unwrap_or_else(make::ty_placeholder);
1384                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1385             }
1386         };
1387         Some(make::ret_type(ret_ty))
1388     }
1389 }
1390
1391 impl FunType {
1392     fn make_ty(&self, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1393         match self {
1394             FunType::Unit => make::ty_unit(),
1395             FunType::Single(ty) => make_ty(ty, ctx, module),
1396             FunType::Tuple(types) => match types.as_slice() {
1397                 [] => {
1398                     stdx::never!("tuple type with 0 elements");
1399                     make::ty_unit()
1400                 }
1401                 [ty] => {
1402                     stdx::never!("tuple type with 1 element");
1403                     make_ty(ty, ctx, module)
1404                 }
1405                 types => {
1406                     let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1407                     make::ty_tuple(types)
1408                 }
1409             },
1410         }
1411     }
1412 }
1413
1414 fn make_body(
1415     ctx: &AssistContext,
1416     old_indent: IndentLevel,
1417     new_indent: IndentLevel,
1418     fun: &Function,
1419 ) -> ast::BlockExpr {
1420     let ret_ty = fun.return_type(ctx);
1421     let handler = if fun.mods.is_in_tail {
1422         FlowHandler::None
1423     } else {
1424         FlowHandler::from_ret_ty(fun, &ret_ty)
1425     };
1426     let block = match &fun.body {
1427         FunctionBody::Expr(expr) => {
1428             let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1429             let expr = ast::Expr::cast(expr).unwrap();
1430             match expr {
1431                 ast::Expr::BlockExpr(block) => {
1432                     // If the extracted expression is itself a block, there is no need to wrap it inside another block.
1433                     let block = block.dedent(old_indent);
1434                     // Recreate the block for formatting consistency with other extracted functions.
1435                     make::block_expr(block.statements(), block.tail_expr())
1436                 }
1437                 _ => {
1438                     let expr = expr.dedent(old_indent).indent(IndentLevel(1));
1439
1440                     make::block_expr(Vec::new(), Some(expr))
1441                 }
1442             }
1443         }
1444         FunctionBody::Span { parent, text_range } => {
1445             let mut elements: Vec<_> = parent
1446                 .syntax()
1447                 .children()
1448                 .filter(|it| text_range.contains_range(it.text_range()))
1449                 .map(|it| rewrite_body_segment(ctx, &fun.params, &handler, &it))
1450                 .collect();
1451
1452             let mut tail_expr = match elements.pop() {
1453                 Some(node) => ast::Expr::cast(node.clone()).or_else(|| {
1454                     elements.push(node);
1455                     None
1456                 }),
1457                 None => None,
1458             };
1459
1460             if tail_expr.is_none() {
1461                 match fun.outliving_locals.as_slice() {
1462                     [] => {}
1463                     [var] => {
1464                         tail_expr = Some(path_expr_from_local(ctx, var.local));
1465                     }
1466                     vars => {
1467                         let exprs = vars.iter().map(|var| path_expr_from_local(ctx, var.local));
1468                         let expr = make::expr_tuple(exprs);
1469                         tail_expr = Some(expr);
1470                     }
1471                 }
1472             }
1473
1474             let elements = elements.into_iter().filter_map(|node| match ast::Stmt::cast(node) {
1475                 Some(stmt) => Some(stmt),
1476                 None => {
1477                     stdx::never!("block contains non-statement");
1478                     None
1479                 }
1480             });
1481
1482             let body_indent = IndentLevel(1);
1483             let elements = elements.map(|stmt| stmt.dedent(old_indent).indent(body_indent));
1484             let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
1485
1486             make::block_expr(elements, tail_expr)
1487         }
1488     };
1489
1490     let block = match &handler {
1491         FlowHandler::None => block,
1492         FlowHandler::Try { kind } => {
1493             let block = with_default_tail_expr(block, make::expr_unit());
1494             map_tail_expr(block, |tail_expr| {
1495                 let constructor = match kind {
1496                     TryKind::Option => "Some",
1497                     TryKind::Result { .. } => "Ok",
1498                 };
1499                 let func = make::expr_path(make::ext::ident_path(constructor));
1500                 let args = make::arg_list(iter::once(tail_expr));
1501                 make::expr_call(func, args)
1502             })
1503         }
1504         FlowHandler::If { .. } => {
1505             let controlflow_continue = make::expr_call(
1506                 make::expr_path(make::path_from_text("ControlFlow::Continue")),
1507                 make::arg_list(iter::once(make::expr_unit())),
1508             );
1509             with_tail_expr(block, controlflow_continue.into())
1510         }
1511         FlowHandler::IfOption { .. } => {
1512             let none = make::expr_path(make::ext::ident_path("None"));
1513             with_tail_expr(block, none)
1514         }
1515         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1516             let some = make::expr_path(make::ext::ident_path("Some"));
1517             let args = make::arg_list(iter::once(tail_expr));
1518             make::expr_call(some, args)
1519         }),
1520         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1521             let ok = make::expr_path(make::ext::ident_path("Ok"));
1522             let args = make::arg_list(iter::once(tail_expr));
1523             make::expr_call(ok, args)
1524         }),
1525     };
1526
1527     block.indent(new_indent)
1528 }
1529
1530 fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1531     let tail_expr = match block.tail_expr() {
1532         Some(tail_expr) => tail_expr,
1533         None => return block,
1534     };
1535     make::block_expr(block.statements(), Some(f(tail_expr)))
1536 }
1537
1538 fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1539     match block.tail_expr() {
1540         Some(_) => block,
1541         None => make::block_expr(block.statements(), Some(tail_expr)),
1542     }
1543 }
1544
1545 fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1546     let stmt_tail = block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1547     let stmts = block.statements().chain(stmt_tail);
1548     make::block_expr(stmts, Some(tail_expr))
1549 }
1550
1551 fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String {
1552     ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string())
1553 }
1554
1555 fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1556     let ty_str = format_type(ty, ctx, module);
1557     make::ty(&ty_str)
1558 }
1559
1560 fn rewrite_body_segment(
1561     ctx: &AssistContext,
1562     params: &[Param],
1563     handler: &FlowHandler,
1564     syntax: &SyntaxNode,
1565 ) -> SyntaxNode {
1566     let syntax = fix_param_usages(ctx, params, syntax);
1567     update_external_control_flow(handler, &syntax);
1568     syntax
1569 }
1570
1571 /// change all usages to account for added `&`/`&mut` for some params
1572 fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode {
1573     let mut usages_for_param: Vec<(&Param, Vec<ast::Expr>)> = Vec::new();
1574
1575     let tm = TreeMutator::new(syntax);
1576
1577     for param in params {
1578         if !param.kind().is_ref() {
1579             continue;
1580         }
1581
1582         let usages = LocalUsages::find_local_usages(ctx, param.var);
1583         let usages = usages
1584             .iter()
1585             .filter(|reference| syntax.text_range().contains_range(reference.range))
1586             .filter_map(|reference| path_element_of_reference(syntax, reference))
1587             .map(|expr| tm.make_mut(&expr));
1588
1589         usages_for_param.push((param, usages.collect()));
1590     }
1591
1592     let res = tm.make_syntax_mut(syntax);
1593
1594     for (param, usages) in usages_for_param {
1595         for usage in usages {
1596             match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
1597                 Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
1598                     // do nothing
1599                 }
1600                 Some(ast::Expr::RefExpr(node))
1601                     if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
1602                 {
1603                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1604                 }
1605                 Some(ast::Expr::RefExpr(node))
1606                     if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
1607                 {
1608                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1609                 }
1610                 Some(_) | None => {
1611                     let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update();
1612                     ted::replace(usage.syntax(), p.syntax())
1613                 }
1614             }
1615         }
1616     }
1617
1618     res
1619 }
1620
1621 fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) {
1622     let mut nested_loop = None;
1623     let mut nested_scope = None;
1624     for event in syntax.preorder() {
1625         match event {
1626             WalkEvent::Enter(e) => match e.kind() {
1627                 SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
1628                     if nested_loop.is_none() {
1629                         nested_loop = Some(e.clone());
1630                     }
1631                 }
1632                 SyntaxKind::FN
1633                 | SyntaxKind::CONST
1634                 | SyntaxKind::STATIC
1635                 | SyntaxKind::IMPL
1636                 | SyntaxKind::MODULE => {
1637                     if nested_scope.is_none() {
1638                         nested_scope = Some(e.clone());
1639                     }
1640                 }
1641                 _ => {}
1642             },
1643             WalkEvent::Leave(e) => {
1644                 if nested_scope.is_none() {
1645                     if let Some(expr) = ast::Expr::cast(e.clone()) {
1646                         match expr {
1647                             ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => {
1648                                 let expr = return_expr.expr();
1649                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1650                                     ted::replace(return_expr.syntax(), replacement.syntax())
1651                                 }
1652                             }
1653                             ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
1654                                 let expr = break_expr.expr();
1655                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1656                                     ted::replace(break_expr.syntax(), replacement.syntax())
1657                                 }
1658                             }
1659                             ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
1660                                 if let Some(replacement) = make_rewritten_flow(handler, None) {
1661                                     ted::replace(continue_expr.syntax(), replacement.syntax())
1662                                 }
1663                             }
1664                             _ => {
1665                                 // do nothing
1666                             }
1667                         }
1668                     }
1669                 }
1670
1671                 if nested_loop.as_ref() == Some(&e) {
1672                     nested_loop = None;
1673                 }
1674                 if nested_scope.as_ref() == Some(&e) {
1675                     nested_scope = None;
1676                 }
1677             }
1678         };
1679     }
1680 }
1681
1682 fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1683     let value = match handler {
1684         FlowHandler::None | FlowHandler::Try { .. } => return None,
1685         FlowHandler::If { .. } => make::expr_call(
1686             make::expr_path(make::path_from_text("ControlFlow::Break")),
1687             make::arg_list(iter::once(make::expr_unit())),
1688         ),
1689         FlowHandler::IfOption { .. } => {
1690             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1691             let args = make::arg_list(iter::once(expr));
1692             make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
1693         }
1694         FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
1695         FlowHandler::MatchResult { .. } => {
1696             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1697             let args = make::arg_list(iter::once(expr));
1698             make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
1699         }
1700     };
1701     Some(make::expr_return(Some(value)).clone_for_update())
1702 }
1703
1704 #[cfg(test)]
1705 mod tests {
1706     use crate::tests::{check_assist, check_assist_not_applicable};
1707
1708     use super::*;
1709
1710     #[test]
1711     fn no_args_from_binary_expr() {
1712         check_assist(
1713             extract_function,
1714             r#"
1715 fn foo() {
1716     foo($01 + 1$0);
1717 }
1718 "#,
1719             r#"
1720 fn foo() {
1721     foo(fun_name());
1722 }
1723
1724 fn $0fun_name() -> i32 {
1725     1 + 1
1726 }
1727 "#,
1728         );
1729     }
1730
1731     #[test]
1732     fn no_args_from_binary_expr_in_module() {
1733         check_assist(
1734             extract_function,
1735             r#"
1736 mod bar {
1737     fn foo() {
1738         foo($01 + 1$0);
1739     }
1740 }
1741 "#,
1742             r#"
1743 mod bar {
1744     fn foo() {
1745         foo(fun_name());
1746     }
1747
1748     fn $0fun_name() -> i32 {
1749         1 + 1
1750     }
1751 }
1752 "#,
1753         );
1754     }
1755
1756     #[test]
1757     fn no_args_from_binary_expr_indented() {
1758         check_assist(
1759             extract_function,
1760             r#"
1761 fn foo() {
1762     $0{ 1 + 1 }$0;
1763 }
1764 "#,
1765             r#"
1766 fn foo() {
1767     fun_name();
1768 }
1769
1770 fn $0fun_name() -> i32 {
1771     1 + 1
1772 }
1773 "#,
1774         );
1775     }
1776
1777     #[test]
1778     fn no_args_from_stmt_with_last_expr() {
1779         check_assist(
1780             extract_function,
1781             r#"
1782 fn foo() -> i32 {
1783     let k = 1;
1784     $0let m = 1;
1785     m + 1$0
1786 }
1787 "#,
1788             r#"
1789 fn foo() -> i32 {
1790     let k = 1;
1791     fun_name()
1792 }
1793
1794 fn $0fun_name() -> i32 {
1795     let m = 1;
1796     m + 1
1797 }
1798 "#,
1799         );
1800     }
1801
1802     #[test]
1803     fn no_args_from_stmt_unit() {
1804         check_assist(
1805             extract_function,
1806             r#"
1807 fn foo() {
1808     let k = 3;
1809     $0let m = 1;
1810     let n = m + 1;$0
1811     let g = 5;
1812 }
1813 "#,
1814             r#"
1815 fn foo() {
1816     let k = 3;
1817     fun_name();
1818     let g = 5;
1819 }
1820
1821 fn $0fun_name() {
1822     let m = 1;
1823     let n = m + 1;
1824 }
1825 "#,
1826         );
1827     }
1828
1829     #[test]
1830     fn no_args_if() {
1831         check_assist(
1832             extract_function,
1833             r#"
1834 fn foo() {
1835     $0if true { }$0
1836 }
1837 "#,
1838             r#"
1839 fn foo() {
1840     fun_name();
1841 }
1842
1843 fn $0fun_name() {
1844     if true { }
1845 }
1846 "#,
1847         );
1848     }
1849
1850     #[test]
1851     fn no_args_if_else() {
1852         check_assist(
1853             extract_function,
1854             r#"
1855 fn foo() -> i32 {
1856     $0if true { 1 } else { 2 }$0
1857 }
1858 "#,
1859             r#"
1860 fn foo() -> i32 {
1861     fun_name()
1862 }
1863
1864 fn $0fun_name() -> i32 {
1865     if true { 1 } else { 2 }
1866 }
1867 "#,
1868         );
1869     }
1870
1871     #[test]
1872     fn no_args_if_let_else() {
1873         check_assist(
1874             extract_function,
1875             r#"
1876 fn foo() -> i32 {
1877     $0if let true = false { 1 } else { 2 }$0
1878 }
1879 "#,
1880             r#"
1881 fn foo() -> i32 {
1882     fun_name()
1883 }
1884
1885 fn $0fun_name() -> i32 {
1886     if let true = false { 1 } else { 2 }
1887 }
1888 "#,
1889         );
1890     }
1891
1892     #[test]
1893     fn no_args_match() {
1894         check_assist(
1895             extract_function,
1896             r#"
1897 fn foo() -> i32 {
1898     $0match true {
1899         true => 1,
1900         false => 2,
1901     }$0
1902 }
1903 "#,
1904             r#"
1905 fn foo() -> i32 {
1906     fun_name()
1907 }
1908
1909 fn $0fun_name() -> i32 {
1910     match true {
1911         true => 1,
1912         false => 2,
1913     }
1914 }
1915 "#,
1916         );
1917     }
1918
1919     #[test]
1920     fn no_args_while() {
1921         check_assist(
1922             extract_function,
1923             r#"
1924 fn foo() {
1925     $0while true { }$0
1926 }
1927 "#,
1928             r#"
1929 fn foo() {
1930     fun_name();
1931 }
1932
1933 fn $0fun_name() {
1934     while true { }
1935 }
1936 "#,
1937         );
1938     }
1939
1940     #[test]
1941     fn no_args_for() {
1942         check_assist(
1943             extract_function,
1944             r#"
1945 fn foo() {
1946     $0for v in &[0, 1] { }$0
1947 }
1948 "#,
1949             r#"
1950 fn foo() {
1951     fun_name();
1952 }
1953
1954 fn $0fun_name() {
1955     for v in &[0, 1] { }
1956 }
1957 "#,
1958         );
1959     }
1960
1961     #[test]
1962     fn no_args_from_loop_unit() {
1963         check_assist(
1964             extract_function,
1965             r#"
1966 fn foo() {
1967     $0loop {
1968         let m = 1;
1969     }$0
1970 }
1971 "#,
1972             r#"
1973 fn foo() {
1974     fun_name()
1975 }
1976
1977 fn $0fun_name() -> ! {
1978     loop {
1979         let m = 1;
1980     }
1981 }
1982 "#,
1983         );
1984     }
1985
1986     #[test]
1987     fn no_args_from_loop_with_return() {
1988         check_assist(
1989             extract_function,
1990             r#"
1991 fn foo() {
1992     let v = $0loop {
1993         let m = 1;
1994         break m;
1995     }$0;
1996 }
1997 "#,
1998             r#"
1999 fn foo() {
2000     let v = fun_name();
2001 }
2002
2003 fn $0fun_name() -> i32 {
2004     loop {
2005         let m = 1;
2006         break m;
2007     }
2008 }
2009 "#,
2010         );
2011     }
2012
2013     #[test]
2014     fn no_args_from_match() {
2015         check_assist(
2016             extract_function,
2017             r#"
2018 fn foo() {
2019     let v: i32 = $0match Some(1) {
2020         Some(x) => x,
2021         None => 0,
2022     }$0;
2023 }
2024 "#,
2025             r#"
2026 fn foo() {
2027     let v: i32 = fun_name();
2028 }
2029
2030 fn $0fun_name() -> i32 {
2031     match Some(1) {
2032         Some(x) => x,
2033         None => 0,
2034     }
2035 }
2036 "#,
2037         );
2038     }
2039
2040     #[test]
2041     fn extract_partial_block_single_line() {
2042         check_assist(
2043             extract_function,
2044             r#"
2045 fn foo() {
2046     let n = 1;
2047     let mut v = $0n * n;$0
2048     v += 1;
2049 }
2050 "#,
2051             r#"
2052 fn foo() {
2053     let n = 1;
2054     let mut v = fun_name(n);
2055     v += 1;
2056 }
2057
2058 fn $0fun_name(n: i32) -> i32 {
2059     let mut v = n * n;
2060     v
2061 }
2062 "#,
2063         );
2064     }
2065
2066     #[test]
2067     fn extract_partial_block() {
2068         check_assist(
2069             extract_function,
2070             r#"
2071 fn foo() {
2072     let m = 2;
2073     let n = 1;
2074     let mut v = m $0* n;
2075     let mut w = 3;$0
2076     v += 1;
2077     w += 1;
2078 }
2079 "#,
2080             r#"
2081 fn foo() {
2082     let m = 2;
2083     let n = 1;
2084     let (mut v, mut w) = fun_name(m, n);
2085     v += 1;
2086     w += 1;
2087 }
2088
2089 fn $0fun_name(m: i32, n: i32) -> (i32, i32) {
2090     let mut v = m * n;
2091     let mut w = 3;
2092     (v, w)
2093 }
2094 "#,
2095         );
2096     }
2097
2098     #[test]
2099     fn argument_form_expr() {
2100         check_assist(
2101             extract_function,
2102             r#"
2103 fn foo() -> u32 {
2104     let n = 2;
2105     $0n+2$0
2106 }
2107 "#,
2108             r#"
2109 fn foo() -> u32 {
2110     let n = 2;
2111     fun_name(n)
2112 }
2113
2114 fn $0fun_name(n: u32) -> u32 {
2115     n+2
2116 }
2117 "#,
2118         )
2119     }
2120
2121     #[test]
2122     fn argument_used_twice_form_expr() {
2123         check_assist(
2124             extract_function,
2125             r#"
2126 fn foo() -> u32 {
2127     let n = 2;
2128     $0n+n$0
2129 }
2130 "#,
2131             r#"
2132 fn foo() -> u32 {
2133     let n = 2;
2134     fun_name(n)
2135 }
2136
2137 fn $0fun_name(n: u32) -> u32 {
2138     n+n
2139 }
2140 "#,
2141         )
2142     }
2143
2144     #[test]
2145     fn two_arguments_form_expr() {
2146         check_assist(
2147             extract_function,
2148             r#"
2149 fn foo() -> u32 {
2150     let n = 2;
2151     let m = 3;
2152     $0n+n*m$0
2153 }
2154 "#,
2155             r#"
2156 fn foo() -> u32 {
2157     let n = 2;
2158     let m = 3;
2159     fun_name(n, m)
2160 }
2161
2162 fn $0fun_name(n: u32, m: u32) -> u32 {
2163     n+n*m
2164 }
2165 "#,
2166         )
2167     }
2168
2169     #[test]
2170     fn argument_and_locals() {
2171         check_assist(
2172             extract_function,
2173             r#"
2174 fn foo() -> u32 {
2175     let n = 2;
2176     $0let m = 1;
2177     n + m$0
2178 }
2179 "#,
2180             r#"
2181 fn foo() -> u32 {
2182     let n = 2;
2183     fun_name(n)
2184 }
2185
2186 fn $0fun_name(n: u32) -> u32 {
2187     let m = 1;
2188     n + m
2189 }
2190 "#,
2191         )
2192     }
2193
2194     #[test]
2195     fn in_comment_is_not_applicable() {
2196         cov_mark::check!(extract_function_in_comment_is_not_applicable);
2197         check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
2198     }
2199
2200     #[test]
2201     fn part_of_expr_stmt() {
2202         check_assist(
2203             extract_function,
2204             r#"
2205 fn foo() {
2206     $01$0 + 1;
2207 }
2208 "#,
2209             r#"
2210 fn foo() {
2211     fun_name() + 1;
2212 }
2213
2214 fn $0fun_name() -> i32 {
2215     1
2216 }
2217 "#,
2218         );
2219     }
2220
2221     #[test]
2222     fn function_expr() {
2223         check_assist(
2224             extract_function,
2225             r#"
2226 fn foo() {
2227     $0bar(1 + 1)$0
2228 }
2229 "#,
2230             r#"
2231 fn foo() {
2232     fun_name();
2233 }
2234
2235 fn $0fun_name() {
2236     bar(1 + 1)
2237 }
2238 "#,
2239         )
2240     }
2241
2242     #[test]
2243     fn extract_from_nested() {
2244         check_assist(
2245             extract_function,
2246             r#"
2247 fn main() {
2248     let x = true;
2249     let tuple = match x {
2250         true => ($02 + 2$0, true)
2251         _ => (0, false)
2252     };
2253 }
2254 "#,
2255             r#"
2256 fn main() {
2257     let x = true;
2258     let tuple = match x {
2259         true => (fun_name(), true)
2260         _ => (0, false)
2261     };
2262 }
2263
2264 fn $0fun_name() -> i32 {
2265     2 + 2
2266 }
2267 "#,
2268         );
2269     }
2270
2271     #[test]
2272     fn param_from_closure() {
2273         check_assist(
2274             extract_function,
2275             r#"
2276 fn main() {
2277     let lambda = |x: u32| $0x * 2$0;
2278 }
2279 "#,
2280             r#"
2281 fn main() {
2282     let lambda = |x: u32| fun_name(x);
2283 }
2284
2285 fn $0fun_name(x: u32) -> u32 {
2286     x * 2
2287 }
2288 "#,
2289         );
2290     }
2291
2292     #[test]
2293     fn extract_return_stmt() {
2294         check_assist(
2295             extract_function,
2296             r#"
2297 fn foo() -> u32 {
2298     $0return 2 + 2$0;
2299 }
2300 "#,
2301             r#"
2302 fn foo() -> u32 {
2303     return fun_name();
2304 }
2305
2306 fn $0fun_name() -> u32 {
2307     2 + 2
2308 }
2309 "#,
2310         );
2311     }
2312
2313     #[test]
2314     fn does_not_add_extra_whitespace() {
2315         check_assist(
2316             extract_function,
2317             r#"
2318 fn foo() -> u32 {
2319
2320
2321     $0return 2 + 2$0;
2322 }
2323 "#,
2324             r#"
2325 fn foo() -> u32 {
2326
2327
2328     return fun_name();
2329 }
2330
2331 fn $0fun_name() -> u32 {
2332     2 + 2
2333 }
2334 "#,
2335         );
2336     }
2337
2338     #[test]
2339     fn break_stmt() {
2340         check_assist(
2341             extract_function,
2342             r#"
2343 fn main() {
2344     let result = loop {
2345         $0break 2 + 2$0;
2346     };
2347 }
2348 "#,
2349             r#"
2350 fn main() {
2351     let result = loop {
2352         break fun_name();
2353     };
2354 }
2355
2356 fn $0fun_name() -> i32 {
2357     2 + 2
2358 }
2359 "#,
2360         );
2361     }
2362
2363     #[test]
2364     fn extract_cast() {
2365         check_assist(
2366             extract_function,
2367             r#"
2368 fn main() {
2369     let v = $00f32 as u32$0;
2370 }
2371 "#,
2372             r#"
2373 fn main() {
2374     let v = fun_name();
2375 }
2376
2377 fn $0fun_name() -> u32 {
2378     0f32 as u32
2379 }
2380 "#,
2381         );
2382     }
2383
2384     #[test]
2385     fn return_not_applicable() {
2386         check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2387     }
2388
2389     #[test]
2390     fn method_to_freestanding() {
2391         check_assist(
2392             extract_function,
2393             r#"
2394 struct S;
2395
2396 impl S {
2397     fn foo(&self) -> i32 {
2398         $01+1$0
2399     }
2400 }
2401 "#,
2402             r#"
2403 struct S;
2404
2405 impl S {
2406     fn foo(&self) -> i32 {
2407         fun_name()
2408     }
2409 }
2410
2411 fn $0fun_name() -> i32 {
2412     1+1
2413 }
2414 "#,
2415         );
2416     }
2417
2418     #[test]
2419     fn method_with_reference() {
2420         check_assist(
2421             extract_function,
2422             r#"
2423 struct S { f: i32 };
2424
2425 impl S {
2426     fn foo(&self) -> i32 {
2427         $0self.f+self.f$0
2428     }
2429 }
2430 "#,
2431             r#"
2432 struct S { f: i32 };
2433
2434 impl S {
2435     fn foo(&self) -> i32 {
2436         self.fun_name()
2437     }
2438
2439     fn $0fun_name(&self) -> i32 {
2440         self.f+self.f
2441     }
2442 }
2443 "#,
2444         );
2445     }
2446
2447     #[test]
2448     fn method_with_mut() {
2449         check_assist(
2450             extract_function,
2451             r#"
2452 struct S { f: i32 };
2453
2454 impl S {
2455     fn foo(&mut self) {
2456         $0self.f += 1;$0
2457     }
2458 }
2459 "#,
2460             r#"
2461 struct S { f: i32 };
2462
2463 impl S {
2464     fn foo(&mut self) {
2465         self.fun_name();
2466     }
2467
2468     fn $0fun_name(&mut self) {
2469         self.f += 1;
2470     }
2471 }
2472 "#,
2473         );
2474     }
2475
2476     #[test]
2477     fn variable_defined_inside_and_used_after_no_ret() {
2478         check_assist(
2479             extract_function,
2480             r#"
2481 fn foo() {
2482     let n = 1;
2483     $0let k = n * n;$0
2484     let m = k + 1;
2485 }
2486 "#,
2487             r#"
2488 fn foo() {
2489     let n = 1;
2490     let k = fun_name(n);
2491     let m = k + 1;
2492 }
2493
2494 fn $0fun_name(n: i32) -> i32 {
2495     let k = n * n;
2496     k
2497 }
2498 "#,
2499         );
2500     }
2501
2502     #[test]
2503     fn variable_defined_inside_and_used_after_mutably_no_ret() {
2504         check_assist(
2505             extract_function,
2506             r#"
2507 fn foo() {
2508     let n = 1;
2509     $0let mut k = n * n;$0
2510     k += 1;
2511 }
2512 "#,
2513             r#"
2514 fn foo() {
2515     let n = 1;
2516     let mut k = fun_name(n);
2517     k += 1;
2518 }
2519
2520 fn $0fun_name(n: i32) -> i32 {
2521     let mut k = n * n;
2522     k
2523 }
2524 "#,
2525         );
2526     }
2527
2528     #[test]
2529     fn two_variables_defined_inside_and_used_after_no_ret() {
2530         check_assist(
2531             extract_function,
2532             r#"
2533 fn foo() {
2534     let n = 1;
2535     $0let k = n * n;
2536     let m = k + 2;$0
2537     let h = k + m;
2538 }
2539 "#,
2540             r#"
2541 fn foo() {
2542     let n = 1;
2543     let (k, m) = fun_name(n);
2544     let h = k + m;
2545 }
2546
2547 fn $0fun_name(n: i32) -> (i32, i32) {
2548     let k = n * n;
2549     let m = k + 2;
2550     (k, m)
2551 }
2552 "#,
2553         );
2554     }
2555
2556     #[test]
2557     fn multi_variables_defined_inside_and_used_after_mutably_no_ret() {
2558         check_assist(
2559             extract_function,
2560             r#"
2561 fn foo() {
2562     let n = 1;
2563     $0let mut k = n * n;
2564     let mut m = k + 2;
2565     let mut o = m + 3;
2566     o += 1;$0
2567     k += o;
2568     m = 1;
2569 }
2570 "#,
2571             r#"
2572 fn foo() {
2573     let n = 1;
2574     let (mut k, mut m, o) = fun_name(n);
2575     k += o;
2576     m = 1;
2577 }
2578
2579 fn $0fun_name(n: i32) -> (i32, i32, i32) {
2580     let mut k = n * n;
2581     let mut m = k + 2;
2582     let mut o = m + 3;
2583     o += 1;
2584     (k, m, o)
2585 }
2586 "#,
2587         );
2588     }
2589
2590     #[test]
2591     fn nontrivial_patterns_define_variables() {
2592         check_assist(
2593             extract_function,
2594             r#"
2595 struct Counter(i32);
2596 fn foo() {
2597     $0let Counter(n) = Counter(0);$0
2598     let m = n;
2599 }
2600 "#,
2601             r#"
2602 struct Counter(i32);
2603 fn foo() {
2604     let n = fun_name();
2605     let m = n;
2606 }
2607
2608 fn $0fun_name() -> i32 {
2609     let Counter(n) = Counter(0);
2610     n
2611 }
2612 "#,
2613         );
2614     }
2615
2616     #[test]
2617     fn struct_with_two_fields_pattern_define_variables() {
2618         check_assist(
2619             extract_function,
2620             r#"
2621 struct Counter { n: i32, m: i32 };
2622 fn foo() {
2623     $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
2624     let h = n + k;
2625 }
2626 "#,
2627             r#"
2628 struct Counter { n: i32, m: i32 };
2629 fn foo() {
2630     let (n, k) = fun_name();
2631     let h = n + k;
2632 }
2633
2634 fn $0fun_name() -> (i32, i32) {
2635     let Counter { n, m: k } = Counter { n: 1, m: 2 };
2636     (n, k)
2637 }
2638 "#,
2639         );
2640     }
2641
2642     #[test]
2643     fn mut_var_from_outer_scope() {
2644         check_assist(
2645             extract_function,
2646             r#"
2647 fn foo() {
2648     let mut n = 1;
2649     $0n += 1;$0
2650     let m = n + 1;
2651 }
2652 "#,
2653             r#"
2654 fn foo() {
2655     let mut n = 1;
2656     fun_name(&mut n);
2657     let m = n + 1;
2658 }
2659
2660 fn $0fun_name(n: &mut i32) {
2661     *n += 1;
2662 }
2663 "#,
2664         );
2665     }
2666
2667     #[test]
2668     fn mut_field_from_outer_scope() {
2669         check_assist(
2670             extract_function,
2671             r#"
2672 struct C { n: i32 }
2673 fn foo() {
2674     let mut c = C { n: 0 };
2675     $0c.n += 1;$0
2676     let m = c.n + 1;
2677 }
2678 "#,
2679             r#"
2680 struct C { n: i32 }
2681 fn foo() {
2682     let mut c = C { n: 0 };
2683     fun_name(&mut c);
2684     let m = c.n + 1;
2685 }
2686
2687 fn $0fun_name(c: &mut C) {
2688     c.n += 1;
2689 }
2690 "#,
2691         );
2692     }
2693
2694     #[test]
2695     fn mut_nested_field_from_outer_scope() {
2696         check_assist(
2697             extract_function,
2698             r#"
2699 struct P { n: i32}
2700 struct C { p: P }
2701 fn foo() {
2702     let mut c = C { p: P { n: 0 } };
2703     let mut v = C { p: P { n: 0 } };
2704     let u = C { p: P { n: 0 } };
2705     $0c.p.n += u.p.n;
2706     let r = &mut v.p.n;$0
2707     let m = c.p.n + v.p.n + u.p.n;
2708 }
2709 "#,
2710             r#"
2711 struct P { n: i32}
2712 struct C { p: P }
2713 fn foo() {
2714     let mut c = C { p: P { n: 0 } };
2715     let mut v = C { p: P { n: 0 } };
2716     let u = C { p: P { n: 0 } };
2717     fun_name(&mut c, &u, &mut v);
2718     let m = c.p.n + v.p.n + u.p.n;
2719 }
2720
2721 fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
2722     c.p.n += u.p.n;
2723     let r = &mut v.p.n;
2724 }
2725 "#,
2726         );
2727     }
2728
2729     #[test]
2730     fn mut_param_many_usages_stmt() {
2731         check_assist(
2732             extract_function,
2733             r#"
2734 fn bar(k: i32) {}
2735 trait I: Copy {
2736     fn succ(&self) -> Self;
2737     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2738 }
2739 impl I for i32 {
2740     fn succ(&self) -> Self { *self + 1 }
2741 }
2742 fn foo() {
2743     let mut n = 1;
2744     $0n += n;
2745     bar(n);
2746     bar(n+1);
2747     bar(n*n);
2748     bar(&n);
2749     n.inc();
2750     let v = &mut n;
2751     *v = v.succ();
2752     n.succ();$0
2753     let m = n + 1;
2754 }
2755 "#,
2756             r#"
2757 fn bar(k: i32) {}
2758 trait I: Copy {
2759     fn succ(&self) -> Self;
2760     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2761 }
2762 impl I for i32 {
2763     fn succ(&self) -> Self { *self + 1 }
2764 }
2765 fn foo() {
2766     let mut n = 1;
2767     fun_name(&mut n);
2768     let m = n + 1;
2769 }
2770
2771 fn $0fun_name(n: &mut i32) {
2772     *n += *n;
2773     bar(*n);
2774     bar(*n+1);
2775     bar(*n**n);
2776     bar(&*n);
2777     n.inc();
2778     let v = n;
2779     *v = v.succ();
2780     n.succ();
2781 }
2782 "#,
2783         );
2784     }
2785
2786     #[test]
2787     fn mut_param_many_usages_expr() {
2788         check_assist(
2789             extract_function,
2790             r#"
2791 fn bar(k: i32) {}
2792 trait I: Copy {
2793     fn succ(&self) -> Self;
2794     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2795 }
2796 impl I for i32 {
2797     fn succ(&self) -> Self { *self + 1 }
2798 }
2799 fn foo() {
2800     let mut n = 1;
2801     $0{
2802         n += n;
2803         bar(n);
2804         bar(n+1);
2805         bar(n*n);
2806         bar(&n);
2807         n.inc();
2808         let v = &mut n;
2809         *v = v.succ();
2810         n.succ();
2811     }$0
2812     let m = n + 1;
2813 }
2814 "#,
2815             r#"
2816 fn bar(k: i32) {}
2817 trait I: Copy {
2818     fn succ(&self) -> Self;
2819     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2820 }
2821 impl I for i32 {
2822     fn succ(&self) -> Self { *self + 1 }
2823 }
2824 fn foo() {
2825     let mut n = 1;
2826     fun_name(&mut n);
2827     let m = n + 1;
2828 }
2829
2830 fn $0fun_name(n: &mut i32) {
2831     *n += *n;
2832     bar(*n);
2833     bar(*n+1);
2834     bar(*n**n);
2835     bar(&*n);
2836     n.inc();
2837     let v = n;
2838     *v = v.succ();
2839     n.succ();
2840 }
2841 "#,
2842         );
2843     }
2844
2845     #[test]
2846     fn mut_param_by_value() {
2847         check_assist(
2848             extract_function,
2849             r#"
2850 fn foo() {
2851     let mut n = 1;
2852     $0n += 1;$0
2853 }
2854 "#,
2855             r"
2856 fn foo() {
2857     let mut n = 1;
2858     fun_name(n);
2859 }
2860
2861 fn $0fun_name(mut n: i32) {
2862     n += 1;
2863 }
2864 ",
2865         );
2866     }
2867
2868     #[test]
2869     fn mut_param_because_of_mut_ref() {
2870         check_assist(
2871             extract_function,
2872             r#"
2873 fn foo() {
2874     let mut n = 1;
2875     $0let v = &mut n;
2876     *v += 1;$0
2877     let k = n;
2878 }
2879 "#,
2880             r#"
2881 fn foo() {
2882     let mut n = 1;
2883     fun_name(&mut n);
2884     let k = n;
2885 }
2886
2887 fn $0fun_name(n: &mut i32) {
2888     let v = n;
2889     *v += 1;
2890 }
2891 "#,
2892         );
2893     }
2894
2895     #[test]
2896     fn mut_param_by_value_because_of_mut_ref() {
2897         check_assist(
2898             extract_function,
2899             r"
2900 fn foo() {
2901     let mut n = 1;
2902     $0let v = &mut n;
2903     *v += 1;$0
2904 }
2905 ",
2906             r#"
2907 fn foo() {
2908     let mut n = 1;
2909     fun_name(n);
2910 }
2911
2912 fn $0fun_name(mut n: i32) {
2913     let v = &mut n;
2914     *v += 1;
2915 }
2916 "#,
2917         );
2918     }
2919
2920     #[test]
2921     fn mut_method_call() {
2922         check_assist(
2923             extract_function,
2924             r#"
2925 trait I {
2926     fn inc(&mut self);
2927 }
2928 impl I for i32 {
2929     fn inc(&mut self) { *self += 1 }
2930 }
2931 fn foo() {
2932     let mut n = 1;
2933     $0n.inc();$0
2934 }
2935 "#,
2936             r#"
2937 trait I {
2938     fn inc(&mut self);
2939 }
2940 impl I for i32 {
2941     fn inc(&mut self) { *self += 1 }
2942 }
2943 fn foo() {
2944     let mut n = 1;
2945     fun_name(n);
2946 }
2947
2948 fn $0fun_name(mut n: i32) {
2949     n.inc();
2950 }
2951 "#,
2952         );
2953     }
2954
2955     #[test]
2956     fn shared_method_call() {
2957         check_assist(
2958             extract_function,
2959             r#"
2960 trait I {
2961     fn succ(&self);
2962 }
2963 impl I for i32 {
2964     fn succ(&self) { *self + 1 }
2965 }
2966 fn foo() {
2967     let mut n = 1;
2968     $0n.succ();$0
2969 }
2970 "#,
2971             r"
2972 trait I {
2973     fn succ(&self);
2974 }
2975 impl I for i32 {
2976     fn succ(&self) { *self + 1 }
2977 }
2978 fn foo() {
2979     let mut n = 1;
2980     fun_name(n);
2981 }
2982
2983 fn $0fun_name(n: i32) {
2984     n.succ();
2985 }
2986 ",
2987         );
2988     }
2989
2990     #[test]
2991     fn mut_method_call_with_other_receiver() {
2992         check_assist(
2993             extract_function,
2994             r#"
2995 trait I {
2996     fn inc(&mut self, n: i32);
2997 }
2998 impl I for i32 {
2999     fn inc(&mut self, n: i32) { *self += n }
3000 }
3001 fn foo() {
3002     let mut n = 1;
3003     $0let mut m = 2;
3004     m.inc(n);$0
3005 }
3006 "#,
3007             r"
3008 trait I {
3009     fn inc(&mut self, n: i32);
3010 }
3011 impl I for i32 {
3012     fn inc(&mut self, n: i32) { *self += n }
3013 }
3014 fn foo() {
3015     let mut n = 1;
3016     fun_name(n);
3017 }
3018
3019 fn $0fun_name(n: i32) {
3020     let mut m = 2;
3021     m.inc(n);
3022 }
3023 ",
3024         );
3025     }
3026
3027     #[test]
3028     fn non_copy_without_usages_after() {
3029         check_assist(
3030             extract_function,
3031             r#"
3032 struct Counter(i32);
3033 fn foo() {
3034     let c = Counter(0);
3035     $0let n = c.0;$0
3036 }
3037 "#,
3038             r"
3039 struct Counter(i32);
3040 fn foo() {
3041     let c = Counter(0);
3042     fun_name(c);
3043 }
3044
3045 fn $0fun_name(c: Counter) {
3046     let n = c.0;
3047 }
3048 ",
3049         );
3050     }
3051
3052     #[test]
3053     fn non_copy_used_after() {
3054         check_assist(
3055             extract_function,
3056             r"
3057 struct Counter(i32);
3058 fn foo() {
3059     let c = Counter(0);
3060     $0let n = c.0;$0
3061     let m = c.0;
3062 }
3063 ",
3064             r#"
3065 struct Counter(i32);
3066 fn foo() {
3067     let c = Counter(0);
3068     fun_name(&c);
3069     let m = c.0;
3070 }
3071
3072 fn $0fun_name(c: &Counter) {
3073     let n = c.0;
3074 }
3075 "#,
3076         );
3077     }
3078
3079     #[test]
3080     fn copy_used_after() {
3081         check_assist(
3082             extract_function,
3083             r#"
3084 //- minicore: copy
3085 fn foo() {
3086     let n = 0;
3087     $0let m = n;$0
3088     let k = n;
3089 }
3090 "#,
3091             r#"
3092 fn foo() {
3093     let n = 0;
3094     fun_name(n);
3095     let k = n;
3096 }
3097
3098 fn $0fun_name(n: i32) {
3099     let m = n;
3100 }
3101 "#,
3102         )
3103     }
3104
3105     #[test]
3106     fn copy_custom_used_after() {
3107         check_assist(
3108             extract_function,
3109             r#"
3110 //- minicore: copy, derive
3111 #[derive(Clone, Copy)]
3112 struct Counter(i32);
3113 fn foo() {
3114     let c = Counter(0);
3115     $0let n = c.0;$0
3116     let m = c.0;
3117 }
3118 "#,
3119             r#"
3120 #[derive(Clone, Copy)]
3121 struct Counter(i32);
3122 fn foo() {
3123     let c = Counter(0);
3124     fun_name(c);
3125     let m = c.0;
3126 }
3127
3128 fn $0fun_name(c: Counter) {
3129     let n = c.0;
3130 }
3131 "#,
3132         );
3133     }
3134
3135     #[test]
3136     fn indented_stmts() {
3137         check_assist(
3138             extract_function,
3139             r#"
3140 fn foo() {
3141     if true {
3142         loop {
3143             $0let n = 1;
3144             let m = 2;$0
3145         }
3146     }
3147 }
3148 "#,
3149             r#"
3150 fn foo() {
3151     if true {
3152         loop {
3153             fun_name();
3154         }
3155     }
3156 }
3157
3158 fn $0fun_name() {
3159     let n = 1;
3160     let m = 2;
3161 }
3162 "#,
3163         );
3164     }
3165
3166     #[test]
3167     fn indented_stmts_inside_mod() {
3168         check_assist(
3169             extract_function,
3170             r#"
3171 mod bar {
3172     fn foo() {
3173         if true {
3174             loop {
3175                 $0let n = 1;
3176                 let m = 2;$0
3177             }
3178         }
3179     }
3180 }
3181 "#,
3182             r#"
3183 mod bar {
3184     fn foo() {
3185         if true {
3186             loop {
3187                 fun_name();
3188             }
3189         }
3190     }
3191
3192     fn $0fun_name() {
3193         let n = 1;
3194         let m = 2;
3195     }
3196 }
3197 "#,
3198         );
3199     }
3200
3201     #[test]
3202     fn break_loop() {
3203         check_assist(
3204             extract_function,
3205             r#"
3206 //- minicore: option
3207 fn foo() {
3208     loop {
3209         let n = 1;
3210         $0let m = n + 1;
3211         break;
3212         let k = 2;$0
3213         let h = 1 + k;
3214     }
3215 }
3216 "#,
3217             r#"
3218 fn foo() {
3219     loop {
3220         let n = 1;
3221         let k = match fun_name(n) {
3222             Some(value) => value,
3223             None => break,
3224         };
3225         let h = 1 + k;
3226     }
3227 }
3228
3229 fn $0fun_name(n: i32) -> Option<i32> {
3230     let m = n + 1;
3231     return None;
3232     let k = 2;
3233     Some(k)
3234 }
3235 "#,
3236         );
3237     }
3238
3239     #[test]
3240     fn return_to_parent() {
3241         check_assist(
3242             extract_function,
3243             r#"
3244 //- minicore: copy, result
3245 fn foo() -> i64 {
3246     let n = 1;
3247     $0let m = n + 1;
3248     return 1;
3249     let k = 2;$0
3250     (n + k) as i64
3251 }
3252 "#,
3253             r#"
3254 fn foo() -> i64 {
3255     let n = 1;
3256     let k = match fun_name(n) {
3257         Ok(value) => value,
3258         Err(value) => return value,
3259     };
3260     (n + k) as i64
3261 }
3262
3263 fn $0fun_name(n: i32) -> Result<i32, i64> {
3264     let m = n + 1;
3265     return Err(1);
3266     let k = 2;
3267     Ok(k)
3268 }
3269 "#,
3270         );
3271     }
3272
3273     #[test]
3274     fn break_and_continue() {
3275         cov_mark::check!(external_control_flow_break_and_continue);
3276         check_assist_not_applicable(
3277             extract_function,
3278             r#"
3279 fn foo() {
3280     loop {
3281         let n = 1;
3282         $0let m = n + 1;
3283         break;
3284         let k = 2;
3285         continue;
3286         let k = k + 1;$0
3287         let r = n + k;
3288     }
3289 }
3290 "#,
3291         );
3292     }
3293
3294     #[test]
3295     fn return_and_break() {
3296         cov_mark::check!(external_control_flow_return_and_bc);
3297         check_assist_not_applicable(
3298             extract_function,
3299             r#"
3300 fn foo() {
3301     loop {
3302         let n = 1;
3303         $0let m = n + 1;
3304         break;
3305         let k = 2;
3306         return;
3307         let k = k + 1;$0
3308         let r = n + k;
3309     }
3310 }
3311 "#,
3312         );
3313     }
3314
3315     #[test]
3316     fn break_loop_with_if() {
3317         check_assist(
3318             extract_function,
3319             r#"
3320 //- minicore: try
3321 fn foo() {
3322     loop {
3323         let mut n = 1;
3324         $0let m = n + 1;
3325         break;
3326         n += m;$0
3327         let h = 1 + n;
3328     }
3329 }
3330 "#,
3331             r#"
3332 use core::ops::ControlFlow;
3333
3334 fn foo() {
3335     loop {
3336         let mut n = 1;
3337         if let ControlFlow::Break(_) = fun_name(&mut n) {
3338             break;
3339         }
3340         let h = 1 + n;
3341     }
3342 }
3343
3344 fn $0fun_name(n: &mut i32) -> ControlFlow<()> {
3345     let m = *n + 1;
3346     return ControlFlow::Break(());
3347     *n += m;
3348     ControlFlow::Continue(())
3349 }
3350 "#,
3351         );
3352     }
3353
3354     #[test]
3355     fn break_loop_nested() {
3356         check_assist(
3357             extract_function,
3358             r#"
3359 //- minicore: try
3360 fn foo() {
3361     loop {
3362         let mut n = 1;
3363         $0let m = n + 1;
3364         if m == 42 {
3365             break;
3366         }$0
3367         let h = 1;
3368     }
3369 }
3370 "#,
3371             r#"
3372 use core::ops::ControlFlow;
3373
3374 fn foo() {
3375     loop {
3376         let mut n = 1;
3377         if let ControlFlow::Break(_) = fun_name(n) {
3378             break;
3379         }
3380         let h = 1;
3381     }
3382 }
3383
3384 fn $0fun_name(n: i32) -> ControlFlow<()> {
3385     let m = n + 1;
3386     if m == 42 {
3387         return ControlFlow::Break(());
3388     }
3389     ControlFlow::Continue(())
3390 }
3391 "#,
3392         );
3393     }
3394
3395     #[test]
3396     fn return_from_nested_loop() {
3397         check_assist(
3398             extract_function,
3399             r#"
3400 fn foo() {
3401     loop {
3402         let n = 1;$0
3403         let k = 1;
3404         loop {
3405             return;
3406         }
3407         let m = k + 1;$0
3408         let h = 1 + m;
3409     }
3410 }
3411 "#,
3412             r#"
3413 fn foo() {
3414     loop {
3415         let n = 1;
3416         let m = match fun_name() {
3417             Some(value) => value,
3418             None => return,
3419         };
3420         let h = 1 + m;
3421     }
3422 }
3423
3424 fn $0fun_name() -> Option<i32> {
3425     let k = 1;
3426     loop {
3427         return None;
3428     }
3429     let m = k + 1;
3430     Some(m)
3431 }
3432 "#,
3433         );
3434     }
3435
3436     #[test]
3437     fn break_from_nested_loop() {
3438         check_assist(
3439             extract_function,
3440             r#"
3441 fn foo() {
3442     loop {
3443         let n = 1;
3444         $0let k = 1;
3445         loop {
3446             break;
3447         }
3448         let m = k + 1;$0
3449         let h = 1 + m;
3450     }
3451 }
3452 "#,
3453             r#"
3454 fn foo() {
3455     loop {
3456         let n = 1;
3457         let m = fun_name();
3458         let h = 1 + m;
3459     }
3460 }
3461
3462 fn $0fun_name() -> i32 {
3463     let k = 1;
3464     loop {
3465         break;
3466     }
3467     let m = k + 1;
3468     m
3469 }
3470 "#,
3471         );
3472     }
3473
3474     #[test]
3475     fn break_from_nested_and_outer_loops() {
3476         check_assist(
3477             extract_function,
3478             r#"
3479 fn foo() {
3480     loop {
3481         let n = 1;
3482         $0let k = 1;
3483         loop {
3484             break;
3485         }
3486         if k == 42 {
3487             break;
3488         }
3489         let m = k + 1;$0
3490         let h = 1 + m;
3491     }
3492 }
3493 "#,
3494             r#"
3495 fn foo() {
3496     loop {
3497         let n = 1;
3498         let m = match fun_name() {
3499             Some(value) => value,
3500             None => break,
3501         };
3502         let h = 1 + m;
3503     }
3504 }
3505
3506 fn $0fun_name() -> Option<i32> {
3507     let k = 1;
3508     loop {
3509         break;
3510     }
3511     if k == 42 {
3512         return None;
3513     }
3514     let m = k + 1;
3515     Some(m)
3516 }
3517 "#,
3518         );
3519     }
3520
3521     #[test]
3522     fn return_from_nested_fn() {
3523         check_assist(
3524             extract_function,
3525             r#"
3526 fn foo() {
3527     loop {
3528         let n = 1;
3529         $0let k = 1;
3530         fn test() {
3531             return;
3532         }
3533         let m = k + 1;$0
3534         let h = 1 + m;
3535     }
3536 }
3537 "#,
3538             r#"
3539 fn foo() {
3540     loop {
3541         let n = 1;
3542         let m = fun_name();
3543         let h = 1 + m;
3544     }
3545 }
3546
3547 fn $0fun_name() -> i32 {
3548     let k = 1;
3549     fn test() {
3550         return;
3551     }
3552     let m = k + 1;
3553     m
3554 }
3555 "#,
3556         );
3557     }
3558
3559     #[test]
3560     fn break_with_value() {
3561         check_assist(
3562             extract_function,
3563             r#"
3564 fn foo() -> i32 {
3565     loop {
3566         let n = 1;
3567         $0let k = 1;
3568         if k == 42 {
3569             break 3;
3570         }
3571         let m = k + 1;$0
3572         let h = 1;
3573     }
3574 }
3575 "#,
3576             r#"
3577 fn foo() -> i32 {
3578     loop {
3579         let n = 1;
3580         if let Some(value) = fun_name() {
3581             break value;
3582         }
3583         let h = 1;
3584     }
3585 }
3586
3587 fn $0fun_name() -> Option<i32> {
3588     let k = 1;
3589     if k == 42 {
3590         return Some(3);
3591     }
3592     let m = k + 1;
3593     None
3594 }
3595 "#,
3596         );
3597     }
3598
3599     #[test]
3600     fn break_with_value_and_return() {
3601         check_assist(
3602             extract_function,
3603             r#"
3604 fn foo() -> i64 {
3605     loop {
3606         let n = 1;$0
3607         let k = 1;
3608         if k == 42 {
3609             break 3;
3610         }
3611         let m = k + 1;$0
3612         let h = 1 + m;
3613     }
3614 }
3615 "#,
3616             r#"
3617 fn foo() -> i64 {
3618     loop {
3619         let n = 1;
3620         let m = match fun_name() {
3621             Ok(value) => value,
3622             Err(value) => break value,
3623         };
3624         let h = 1 + m;
3625     }
3626 }
3627
3628 fn $0fun_name() -> Result<i32, i64> {
3629     let k = 1;
3630     if k == 42 {
3631         return Err(3);
3632     }
3633     let m = k + 1;
3634     Ok(m)
3635 }
3636 "#,
3637         );
3638     }
3639
3640     #[test]
3641     fn try_option() {
3642         check_assist(
3643             extract_function,
3644             r#"
3645 //- minicore: option
3646 fn bar() -> Option<i32> { None }
3647 fn foo() -> Option<()> {
3648     let n = bar()?;
3649     $0let k = foo()?;
3650     let m = k + 1;$0
3651     let h = 1 + m;
3652     Some(())
3653 }
3654 "#,
3655             r#"
3656 fn bar() -> Option<i32> { None }
3657 fn foo() -> Option<()> {
3658     let n = bar()?;
3659     let m = fun_name()?;
3660     let h = 1 + m;
3661     Some(())
3662 }
3663
3664 fn $0fun_name() -> Option<i32> {
3665     let k = foo()?;
3666     let m = k + 1;
3667     Some(m)
3668 }
3669 "#,
3670         );
3671     }
3672
3673     #[test]
3674     fn try_option_unit() {
3675         check_assist(
3676             extract_function,
3677             r#"
3678 //- minicore: option
3679 fn foo() -> Option<()> {
3680     let n = 1;
3681     $0let k = foo()?;
3682     let m = k + 1;$0
3683     let h = 1 + n;
3684     Some(())
3685 }
3686 "#,
3687             r#"
3688 fn foo() -> Option<()> {
3689     let n = 1;
3690     fun_name()?;
3691     let h = 1 + n;
3692     Some(())
3693 }
3694
3695 fn $0fun_name() -> Option<()> {
3696     let k = foo()?;
3697     let m = k + 1;
3698     Some(())
3699 }
3700 "#,
3701         );
3702     }
3703
3704     #[test]
3705     fn try_result() {
3706         check_assist(
3707             extract_function,
3708             r#"
3709 //- minicore: result
3710 fn foo() -> Result<(), i64> {
3711     let n = 1;
3712     $0let k = foo()?;
3713     let m = k + 1;$0
3714     let h = 1 + m;
3715     Ok(())
3716 }
3717 "#,
3718             r#"
3719 fn foo() -> Result<(), i64> {
3720     let n = 1;
3721     let m = fun_name()?;
3722     let h = 1 + m;
3723     Ok(())
3724 }
3725
3726 fn $0fun_name() -> Result<i32, i64> {
3727     let k = foo()?;
3728     let m = k + 1;
3729     Ok(m)
3730 }
3731 "#,
3732         );
3733     }
3734
3735     #[test]
3736     fn try_option_with_return() {
3737         check_assist(
3738             extract_function,
3739             r#"
3740 //- minicore: option
3741 fn foo() -> Option<()> {
3742     let n = 1;
3743     $0let k = foo()?;
3744     if k == 42 {
3745         return None;
3746     }
3747     let m = k + 1;$0
3748     let h = 1 + m;
3749     Some(())
3750 }
3751 "#,
3752             r#"
3753 fn foo() -> Option<()> {
3754     let n = 1;
3755     let m = fun_name()?;
3756     let h = 1 + m;
3757     Some(())
3758 }
3759
3760 fn $0fun_name() -> Option<i32> {
3761     let k = foo()?;
3762     if k == 42 {
3763         return None;
3764     }
3765     let m = k + 1;
3766     Some(m)
3767 }
3768 "#,
3769         );
3770     }
3771
3772     #[test]
3773     fn try_result_with_return() {
3774         check_assist(
3775             extract_function,
3776             r#"
3777 //- minicore: result
3778 fn foo() -> Result<(), i64> {
3779     let n = 1;
3780     $0let k = foo()?;
3781     if k == 42 {
3782         return Err(1);
3783     }
3784     let m = k + 1;$0
3785     let h = 1 + m;
3786     Ok(())
3787 }
3788 "#,
3789             r#"
3790 fn foo() -> Result<(), i64> {
3791     let n = 1;
3792     let m = fun_name()?;
3793     let h = 1 + m;
3794     Ok(())
3795 }
3796
3797 fn $0fun_name() -> Result<i32, i64> {
3798     let k = foo()?;
3799     if k == 42 {
3800         return Err(1);
3801     }
3802     let m = k + 1;
3803     Ok(m)
3804 }
3805 "#,
3806         );
3807     }
3808
3809     #[test]
3810     fn try_and_break() {
3811         cov_mark::check!(external_control_flow_try_and_bc);
3812         check_assist_not_applicable(
3813             extract_function,
3814             r#"
3815 //- minicore: option
3816 fn foo() -> Option<()> {
3817     loop {
3818         let n = Some(1);
3819         $0let m = n? + 1;
3820         break;
3821         let k = 2;
3822         let k = k + 1;$0
3823         let r = n + k;
3824     }
3825     Some(())
3826 }
3827 "#,
3828         );
3829     }
3830
3831     #[test]
3832     fn try_and_return_ok() {
3833         check_assist(
3834             extract_function,
3835             r#"
3836 //- minicore: result
3837 fn foo() -> Result<(), i64> {
3838     let n = 1;
3839     $0let k = foo()?;
3840     if k == 42 {
3841         return Ok(1);
3842     }
3843     let m = k + 1;$0
3844     let h = 1 + m;
3845     Ok(())
3846 }
3847 "#,
3848             r#"
3849 fn foo() -> Result<(), i64> {
3850     let n = 1;
3851     let m = fun_name()?;
3852     let h = 1 + m;
3853     Ok(())
3854 }
3855
3856 fn $0fun_name() -> Result<i32, i64> {
3857     let k = foo()?;
3858     if k == 42 {
3859         return Ok(1);
3860     }
3861     let m = k + 1;
3862     Ok(m)
3863 }
3864 "#,
3865         );
3866     }
3867
3868     #[test]
3869     fn param_usage_in_macro() {
3870         check_assist(
3871             extract_function,
3872             r#"
3873 macro_rules! m {
3874     ($val:expr) => { $val };
3875 }
3876
3877 fn foo() {
3878     let n = 1;
3879     $0let k = n * m!(n);$0
3880     let m = k + 1;
3881 }
3882 "#,
3883             r#"
3884 macro_rules! m {
3885     ($val:expr) => { $val };
3886 }
3887
3888 fn foo() {
3889     let n = 1;
3890     let k = fun_name(n);
3891     let m = k + 1;
3892 }
3893
3894 fn $0fun_name(n: i32) -> i32 {
3895     let k = n * m!(n);
3896     k
3897 }
3898 "#,
3899         );
3900     }
3901
3902     #[test]
3903     fn extract_with_await() {
3904         check_assist(
3905             extract_function,
3906             r#"
3907 fn main() {
3908     $0some_function().await;$0
3909 }
3910
3911 async fn some_function() {
3912
3913 }
3914 "#,
3915             r#"
3916 fn main() {
3917     fun_name().await;
3918 }
3919
3920 async fn $0fun_name() {
3921     some_function().await;
3922 }
3923
3924 async fn some_function() {
3925
3926 }
3927 "#,
3928         );
3929     }
3930
3931     #[test]
3932     fn extract_with_await_and_result_not_producing_match_expr() {
3933         check_assist(
3934             extract_function,
3935             r#"
3936 async fn foo() -> Result<(), ()> {
3937     $0async {}.await;
3938     Err(())?$0
3939 }
3940 "#,
3941             r#"
3942 async fn foo() -> Result<(), ()> {
3943     fun_name().await?
3944 }
3945
3946 async fn $0fun_name() -> _ {
3947     async {}.await;
3948     Err(())?
3949 }
3950 "#,
3951         );
3952     }
3953
3954     #[test]
3955     fn extract_with_await_and_result_producing_match_expr() {
3956         check_assist(
3957             extract_function,
3958             r#"
3959 async fn foo() -> i32 {
3960     loop {
3961         let n = 1;$0
3962         let k = async { 1 }.await;
3963         if k == 42 {
3964             break 3;
3965         }
3966         let m = k + 1;$0
3967         let h = 1 + m;
3968     }
3969 }
3970 "#,
3971             r#"
3972 async fn foo() -> i32 {
3973     loop {
3974         let n = 1;
3975         let m = match fun_name().await {
3976             Ok(value) => value,
3977             Err(value) => break value,
3978         };
3979         let h = 1 + m;
3980     }
3981 }
3982
3983 async fn $0fun_name() -> Result<i32, i32> {
3984     let k = async { 1 }.await;
3985     if k == 42 {
3986         return Err(3);
3987     }
3988     let m = k + 1;
3989     Ok(m)
3990 }
3991 "#,
3992         );
3993     }
3994
3995     #[test]
3996     fn extract_with_await_in_args() {
3997         check_assist(
3998             extract_function,
3999             r#"
4000 fn main() {
4001     $0function_call("a", some_function().await);$0
4002 }
4003
4004 async fn some_function() {
4005
4006 }
4007 "#,
4008             r#"
4009 fn main() {
4010     fun_name().await;
4011 }
4012
4013 async fn $0fun_name() {
4014     function_call("a", some_function().await);
4015 }
4016
4017 async fn some_function() {
4018
4019 }
4020 "#,
4021         );
4022     }
4023
4024     #[test]
4025     fn extract_does_not_extract_standalone_blocks() {
4026         check_assist_not_applicable(
4027             extract_function,
4028             r#"
4029 fn main() $0{}$0
4030 "#,
4031         );
4032     }
4033
4034     #[test]
4035     fn extract_adds_comma_for_match_arm() {
4036         check_assist(
4037             extract_function,
4038             r#"
4039 fn main() {
4040     match 6 {
4041         100 => $0{ 100 }$0
4042         _ => 0,
4043     }
4044 }
4045 "#,
4046             r#"
4047 fn main() {
4048     match 6 {
4049         100 => fun_name(),
4050         _ => 0,
4051     }
4052 }
4053
4054 fn $0fun_name() -> i32 {
4055     100
4056 }
4057 "#,
4058         );
4059         check_assist(
4060             extract_function,
4061             r#"
4062 fn main() {
4063     match 6 {
4064         100 => $0{ 100 }$0,
4065         _ => 0,
4066     }
4067 }
4068 "#,
4069             r#"
4070 fn main() {
4071     match 6 {
4072         100 => fun_name(),
4073         _ => 0,
4074     }
4075 }
4076
4077 fn $0fun_name() -> i32 {
4078     100
4079 }
4080 "#,
4081         );
4082     }
4083
4084     #[test]
4085     fn extract_does_not_tear_comments_apart() {
4086         check_assist(
4087             extract_function,
4088             r#"
4089 fn foo() {
4090     /*$0*/
4091     foo();
4092     foo();
4093     /*$0*/
4094 }
4095 "#,
4096             r#"
4097 fn foo() {
4098     /**/
4099     fun_name();
4100     /**/
4101 }
4102
4103 fn $0fun_name() {
4104     foo();
4105     foo();
4106 }
4107 "#,
4108         );
4109     }
4110
4111     #[test]
4112     fn extract_does_not_wrap_res_in_res() {
4113         check_assist(
4114             extract_function,
4115             r#"
4116 //- minicore: result
4117 fn foo() -> Result<(), i64> {
4118     $0Result::<i32, i64>::Ok(0)?;
4119     Ok(())$0
4120 }
4121 "#,
4122             r#"
4123 fn foo() -> Result<(), i64> {
4124     fun_name()?
4125 }
4126
4127 fn $0fun_name() -> Result<(), i64> {
4128     Result::<i32, i64>::Ok(0)?;
4129     Ok(())
4130 }
4131 "#,
4132         );
4133     }
4134
4135     #[test]
4136     fn extract_knows_const() {
4137         check_assist(
4138             extract_function,
4139             r#"
4140 const fn foo() {
4141     $0()$0
4142 }
4143 "#,
4144             r#"
4145 const fn foo() {
4146     fun_name();
4147 }
4148
4149 const fn $0fun_name() {
4150     ()
4151 }
4152 "#,
4153         );
4154         check_assist(
4155             extract_function,
4156             r#"
4157 const FOO: () = {
4158     $0()$0
4159 };
4160 "#,
4161             r#"
4162 const FOO: () = {
4163     fun_name();
4164 };
4165
4166 const fn $0fun_name() {
4167     ()
4168 }
4169 "#,
4170         );
4171     }
4172
4173     #[test]
4174     fn extract_does_not_move_outer_loop_vars() {
4175         check_assist(
4176             extract_function,
4177             r#"
4178 fn foo() {
4179     let mut x = 5;
4180     for _ in 0..10 {
4181         $0x += 1;$0
4182     }
4183 }
4184 "#,
4185             r#"
4186 fn foo() {
4187     let mut x = 5;
4188     for _ in 0..10 {
4189         fun_name(&mut x);
4190     }
4191 }
4192
4193 fn $0fun_name(x: &mut i32) {
4194     *x += 1;
4195 }
4196 "#,
4197         );
4198         check_assist(
4199             extract_function,
4200             r#"
4201 fn foo() {
4202     for _ in 0..10 {
4203         let mut x = 5;
4204         $0x += 1;$0
4205     }
4206 }
4207 "#,
4208             r#"
4209 fn foo() {
4210     for _ in 0..10 {
4211         let mut x = 5;
4212         fun_name(x);
4213     }
4214 }
4215
4216 fn $0fun_name(mut x: i32) {
4217     x += 1;
4218 }
4219 "#,
4220         );
4221         check_assist(
4222             extract_function,
4223             r#"
4224 fn foo() {
4225     loop {
4226         let mut x = 5;
4227         for _ in 0..10 {
4228             $0x += 1;$0
4229         }
4230     }
4231 }
4232 "#,
4233             r#"
4234 fn foo() {
4235     loop {
4236         let mut x = 5;
4237         for _ in 0..10 {
4238             fun_name(&mut x);
4239         }
4240     }
4241 }
4242
4243 fn $0fun_name(x: &mut i32) {
4244     *x += 1;
4245 }
4246 "#,
4247         );
4248     }
4249
4250     // regression test for #9822
4251     #[test]
4252     fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4253         check_assist(
4254             extract_function,
4255             r#"
4256 struct Foo;
4257 impl Foo {
4258     fn foo(&mut self) {}
4259 }
4260 fn foo() {
4261     let mut x = Foo;
4262     while false {
4263         let y = &mut x;
4264         $0y.foo();$0
4265     }
4266     let z = x;
4267 }
4268 "#,
4269             r#"
4270 struct Foo;
4271 impl Foo {
4272     fn foo(&mut self) {}
4273 }
4274 fn foo() {
4275     let mut x = Foo;
4276     while false {
4277         let y = &mut x;
4278         fun_name(y);
4279     }
4280     let z = x;
4281 }
4282
4283 fn $0fun_name(y: &mut Foo) {
4284     y.foo();
4285 }
4286 "#,
4287         );
4288     }
4289
4290     #[test]
4291     fn extract_with_macro_arg() {
4292         check_assist(
4293             extract_function,
4294             r#"
4295 macro_rules! m {
4296     ($val:expr) => { $val };
4297 }
4298 fn main() {
4299     let bar = "bar";
4300     $0m!(bar);$0
4301 }
4302 "#,
4303             r#"
4304 macro_rules! m {
4305     ($val:expr) => { $val };
4306 }
4307 fn main() {
4308     let bar = "bar";
4309     fun_name(bar);
4310 }
4311
4312 fn $0fun_name(bar: &str) {
4313     m!(bar);
4314 }
4315 "#,
4316         );
4317     }
4318
4319     #[test]
4320     fn unresolveable_types_default_to_placeholder() {
4321         check_assist(
4322             extract_function,
4323             r#"
4324 fn foo() {
4325     let a = __unresolved;
4326     let _ = $0{a}$0;
4327 }
4328 "#,
4329             r#"
4330 fn foo() {
4331     let a = __unresolved;
4332     let _ = fun_name(a);
4333 }
4334
4335 fn $0fun_name(a: _) -> _ {
4336     a
4337 }
4338 "#,
4339         );
4340     }
4341 }