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