]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/extract_function.rs
Merge #10438
[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.frange.range;
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.clone());
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_many(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)| {
831                 if let Either::Left(src) = src.value {
832                     Some((local, src))
833                 } else {
834                     stdx::never!(false, "Local::is_self returned false, but source is SelfParam");
835                     None
836                 }
837             })
838             .map(|(var, src)| {
839                 let usages = LocalUsages::find_local_usages(ctx, var);
840                 let ty = var.ty(ctx.db());
841
842                 let defined_outside_parent_loop = container_info
843                     .parent_loop
844                     .as_ref()
845                     .map_or(true, |it| it.text_range().contains_range(src.syntax().text_range()));
846
847                 let is_copy = ty.is_copy(ctx.db());
848                 let has_usages = self.has_usages_after_body(&usages);
849                 let requires_mut =
850                     !ty.is_mutable_reference() && has_exclusive_usages(ctx, &usages, self);
851                 // We can move the value into the function call if it's not used after the call,
852                 // if the var is not used but defined outside a loop we are extracting from we can't move it either
853                 // as the function will reuse it in the next iteration.
854                 let move_local = !has_usages && defined_outside_parent_loop;
855                 Param { var, ty, move_local, requires_mut, is_copy }
856             })
857             .collect()
858     }
859
860     fn has_usages_after_body(&self, usages: &LocalUsages) -> bool {
861         usages.iter().any(|reference| self.precedes_range(reference.range))
862     }
863 }
864
865 /// checks if relevant var is used with `&mut` access inside body
866 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
867     usages
868         .iter()
869         .filter(|reference| body.contains_range(reference.range))
870         .any(|reference| reference_is_exclusive(reference, body, ctx))
871 }
872
873 /// checks if this reference requires `&mut` access inside node
874 fn reference_is_exclusive(
875     reference: &FileReference,
876     node: &dyn HasTokenAtOffset,
877     ctx: &AssistContext,
878 ) -> bool {
879     // we directly modify variable with set: `n = 0`, `n += 1`
880     if reference.category == Some(ReferenceCategory::Write) {
881         return true;
882     }
883
884     // we take `&mut` reference to variable: `&mut v`
885     let path = match path_element_of_reference(node, reference) {
886         Some(path) => path,
887         None => return false,
888     };
889
890     expr_require_exclusive_access(ctx, &path).unwrap_or(false)
891 }
892
893 /// checks if this expr requires `&mut` access, recurses on field access
894 fn expr_require_exclusive_access(ctx: &AssistContext, expr: &ast::Expr) -> Option<bool> {
895     if let ast::Expr::MacroCall(_) = expr {
896         // FIXME: expand macro and check output for mutable usages of the variable?
897         return None;
898     }
899
900     let parent = expr.syntax().parent()?;
901
902     if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
903         if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
904             return Some(bin_expr.lhs()?.syntax() == expr.syntax());
905         }
906         return Some(false);
907     }
908
909     if let Some(ref_expr) = ast::RefExpr::cast(parent.clone()) {
910         return Some(ref_expr.mut_token().is_some());
911     }
912
913     if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
914         let func = ctx.sema.resolve_method_call(&method_call)?;
915         let self_param = func.self_param(ctx.db())?;
916         let access = self_param.access(ctx.db());
917
918         return Some(matches!(access, hir::Access::Exclusive));
919     }
920
921     if let Some(field) = ast::FieldExpr::cast(parent) {
922         return expr_require_exclusive_access(ctx, &field.into());
923     }
924
925     Some(false)
926 }
927
928 trait HasTokenAtOffset {
929     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken>;
930 }
931
932 impl HasTokenAtOffset for SyntaxNode {
933     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
934         SyntaxNode::token_at_offset(self, offset)
935     }
936 }
937
938 impl HasTokenAtOffset for FunctionBody {
939     fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
940         match self {
941             FunctionBody::Expr(expr) => expr.syntax().token_at_offset(offset),
942             FunctionBody::Span { parent, text_range } => {
943                 match parent.syntax().token_at_offset(offset) {
944                     TokenAtOffset::None => TokenAtOffset::None,
945                     TokenAtOffset::Single(t) => {
946                         if text_range.contains_range(t.text_range()) {
947                             TokenAtOffset::Single(t)
948                         } else {
949                             TokenAtOffset::None
950                         }
951                     }
952                     TokenAtOffset::Between(a, b) => {
953                         match (
954                             text_range.contains_range(a.text_range()),
955                             text_range.contains_range(b.text_range()),
956                         ) {
957                             (true, true) => TokenAtOffset::Between(a, b),
958                             (true, false) => TokenAtOffset::Single(a),
959                             (false, true) => TokenAtOffset::Single(b),
960                             (false, false) => TokenAtOffset::None,
961                         }
962                     }
963                 }
964             }
965         }
966     }
967 }
968
969 /// find relevant `ast::Expr` for reference
970 ///
971 /// # Preconditions
972 ///
973 /// `node` must cover `reference`, that is `node.text_range().contains_range(reference.range)`
974 fn path_element_of_reference(
975     node: &dyn HasTokenAtOffset,
976     reference: &FileReference,
977 ) -> Option<ast::Expr> {
978     let token = node.token_at_offset(reference.range.start()).right_biased().or_else(|| {
979         stdx::never!(false, "cannot find token at variable usage: {:?}", reference);
980         None
981     })?;
982     let path = token.ancestors().find_map(ast::Expr::cast).or_else(|| {
983         stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
984         None
985     })?;
986     stdx::always!(
987         matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroCall(_)),
988         "unexpected expression type for variable usage: {:?}",
989         path
990     );
991     Some(path)
992 }
993
994 /// list local variables defined inside `body`
995 fn locals_defined_in_body(
996     sema: &Semantics<RootDatabase>,
997     body: &FunctionBody,
998 ) -> FxIndexSet<Local> {
999     // FIXME: this doesn't work well with macros
1000     //        see https://github.com/rust-analyzer/rust-analyzer/pull/7535#discussion_r570048550
1001     let mut res = FxIndexSet::default();
1002     body.walk_pat(&mut |pat| {
1003         if let ast::Pat::IdentPat(pat) = pat {
1004             if let Some(local) = sema.to_def(&pat) {
1005                 res.insert(local);
1006             }
1007         }
1008     });
1009     res
1010 }
1011
1012 /// Returns usage details if local variable is used after(outside of) body
1013 fn local_outlives_body(
1014     ctx: &AssistContext,
1015     body_range: TextRange,
1016     local: Local,
1017     parent: &SyntaxNode,
1018 ) -> Option<OutlivedLocal> {
1019     let usages = LocalUsages::find_local_usages(ctx, local);
1020     let mut has_mut_usages = false;
1021     let mut any_outlives = false;
1022     for usage in usages.iter() {
1023         if body_range.end() <= usage.range.start() {
1024             has_mut_usages |= reference_is_exclusive(usage, parent, ctx);
1025             any_outlives |= true;
1026             if has_mut_usages {
1027                 break; // no need to check more elements we have all the info we wanted
1028             }
1029         }
1030     }
1031     if !any_outlives {
1032         return None;
1033     }
1034     Some(OutlivedLocal { local, mut_usage_outside_body: has_mut_usages })
1035 }
1036
1037 /// checks if the relevant local was defined before(outside of) body
1038 fn is_defined_outside_of_body(
1039     ctx: &AssistContext,
1040     body: &FunctionBody,
1041     src: &hir::InFile<Either<ast::IdentPat, ast::SelfParam>>,
1042 ) -> bool {
1043     src.file_id.original_file(ctx.db()) == ctx.frange.file_id
1044         && !body.contains_node(either_syntax(&src.value))
1045 }
1046
1047 fn either_syntax(value: &Either<ast::IdentPat, ast::SelfParam>) -> &SyntaxNode {
1048     match value {
1049         Either::Left(pat) => pat.syntax(),
1050         Either::Right(it) => it.syntax(),
1051     }
1052 }
1053
1054 /// find where to put extracted function definition
1055 ///
1056 /// Function should be put right after returned node
1057 fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNode> {
1058     let node = match body {
1059         FunctionBody::Expr(e) => e.syntax(),
1060         FunctionBody::Span { parent, .. } => parent.syntax(),
1061     };
1062     let mut ancestors = node.ancestors().peekable();
1063     let mut last_ancestor = None;
1064     while let Some(next_ancestor) = ancestors.next() {
1065         match next_ancestor.kind() {
1066             SyntaxKind::SOURCE_FILE => break,
1067             SyntaxKind::ITEM_LIST if !matches!(anchor, Anchor::Freestanding) => continue,
1068             SyntaxKind::ITEM_LIST => {
1069                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
1070                     break;
1071                 }
1072             }
1073             SyntaxKind::ASSOC_ITEM_LIST if !matches!(anchor, Anchor::Method) => {
1074                 continue;
1075             }
1076             SyntaxKind::ASSOC_ITEM_LIST => {
1077                 if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::IMPL) {
1078                     break;
1079                 }
1080             }
1081             _ => (),
1082         }
1083         last_ancestor = Some(next_ancestor);
1084     }
1085     last_ancestor
1086 }
1087
1088 fn make_call(ctx: &AssistContext, fun: &Function, indent: IndentLevel) -> String {
1089     let ret_ty = fun.return_type(ctx);
1090
1091     let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx)));
1092     let name = fun.name.clone();
1093     let mut call_expr = if fun.self_param.is_some() {
1094         let self_arg = make::expr_path(make::ext::ident_path("self"));
1095         make::expr_method_call(self_arg, name, args)
1096     } else {
1097         let func = make::expr_path(make::path_unqualified(make::path_segment(name)));
1098         make::expr_call(func, args)
1099     };
1100
1101     let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1102
1103     if fun.control_flow.is_async {
1104         call_expr = make::expr_await(call_expr);
1105     }
1106     let expr = handler.make_call_expr(call_expr).indent(indent);
1107
1108     let mut_modifier = |var: &OutlivedLocal| if var.mut_usage_outside_body { "mut " } else { "" };
1109
1110     let mut buf = String::new();
1111     match fun.outliving_locals.as_slice() {
1112         [] => {}
1113         [var] => {
1114             format_to!(buf, "let {}{} = ", mut_modifier(var), var.local.name(ctx.db()).unwrap())
1115         }
1116         vars => {
1117             buf.push_str("let (");
1118             let bindings = vars.iter().format_with(", ", |local, f| {
1119                 f(&format_args!("{}{}", mut_modifier(local), local.local.name(ctx.db()).unwrap()))
1120             });
1121             format_to!(buf, "{}", bindings);
1122             buf.push_str(") = ");
1123         }
1124     }
1125
1126     format_to!(buf, "{}", expr);
1127     let insert_comma = fun
1128         .body
1129         .parent()
1130         .and_then(ast::MatchArm::cast)
1131         .map_or(false, |it| it.comma_token().is_none());
1132     if insert_comma {
1133         buf.push(',');
1134     } else if fun.ret_ty.is_unit() && (!fun.outliving_locals.is_empty() || !expr.is_block_like()) {
1135         buf.push(';');
1136     }
1137     buf
1138 }
1139
1140 enum FlowHandler {
1141     None,
1142     Try { kind: TryKind },
1143     If { action: FlowKind },
1144     IfOption { action: FlowKind },
1145     MatchOption { none: FlowKind },
1146     MatchResult { err: FlowKind },
1147 }
1148
1149 impl FlowHandler {
1150     fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
1151         match &fun.control_flow.kind {
1152             None => FlowHandler::None,
1153             Some(flow_kind) => {
1154                 let action = flow_kind.clone();
1155                 if *ret_ty == FunType::Unit {
1156                     match flow_kind {
1157                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1158                             FlowHandler::If { action }
1159                         }
1160                         FlowKind::Return(_) | FlowKind::Break(_) => {
1161                             FlowHandler::IfOption { action }
1162                         }
1163                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1164                     }
1165                 } else {
1166                     match flow_kind {
1167                         FlowKind::Return(None) | FlowKind::Break(None) | FlowKind::Continue => {
1168                             FlowHandler::MatchOption { none: action }
1169                         }
1170                         FlowKind::Return(_) | FlowKind::Break(_) => {
1171                             FlowHandler::MatchResult { err: action }
1172                         }
1173                         FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
1174                     }
1175                 }
1176             }
1177         }
1178     }
1179
1180     fn make_call_expr(&self, call_expr: ast::Expr) -> ast::Expr {
1181         match self {
1182             FlowHandler::None => call_expr,
1183             FlowHandler::Try { kind: _ } => make::expr_try(call_expr),
1184             FlowHandler::If { action } => {
1185                 let action = action.make_result_handler(None);
1186                 let stmt = make::expr_stmt(action);
1187                 let block = make::block_expr(iter::once(stmt.into()), None);
1188                 let condition = make::condition(call_expr, None);
1189                 make::expr_if(condition, block, None)
1190             }
1191             FlowHandler::IfOption { action } => {
1192                 let path = make::ext::ident_path("Some");
1193                 let value_pat = make::ext::simple_ident_pat(make::name("value"));
1194                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1195                 let cond = make::condition(call_expr, Some(pattern.into()));
1196                 let value = make::expr_path(make::ext::ident_path("value"));
1197                 let action_expr = action.make_result_handler(Some(value));
1198                 let action_stmt = make::expr_stmt(action_expr);
1199                 let then = make::block_expr(iter::once(action_stmt.into()), None);
1200                 make::expr_if(cond, then, None)
1201             }
1202             FlowHandler::MatchOption { none } => {
1203                 let some_name = "value";
1204
1205                 let some_arm = {
1206                     let path = make::ext::ident_path("Some");
1207                     let value_pat = make::ext::simple_ident_pat(make::name(some_name));
1208                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1209                     let value = make::expr_path(make::ext::ident_path(some_name));
1210                     make::match_arm(iter::once(pat.into()), None, value)
1211                 };
1212                 let none_arm = {
1213                     let path = make::ext::ident_path("None");
1214                     let pat = make::path_pat(path);
1215                     make::match_arm(iter::once(pat), None, none.make_result_handler(None))
1216                 };
1217                 let arms = make::match_arm_list(vec![some_arm, none_arm]);
1218                 make::expr_match(call_expr, arms)
1219             }
1220             FlowHandler::MatchResult { err } => {
1221                 let ok_name = "value";
1222                 let err_name = "value";
1223
1224                 let ok_arm = {
1225                     let path = make::ext::ident_path("Ok");
1226                     let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
1227                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1228                     let value = make::expr_path(make::ext::ident_path(ok_name));
1229                     make::match_arm(iter::once(pat.into()), None, value)
1230                 };
1231                 let err_arm = {
1232                     let path = make::ext::ident_path("Err");
1233                     let value_pat = make::ext::simple_ident_pat(make::name(err_name));
1234                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1235                     let value = make::expr_path(make::ext::ident_path(err_name));
1236                     make::match_arm(
1237                         iter::once(pat.into()),
1238                         None,
1239                         err.make_result_handler(Some(value)),
1240                     )
1241                 };
1242                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1243                 make::expr_match(call_expr, arms)
1244             }
1245         }
1246     }
1247 }
1248
1249 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1250     let name = var.name(ctx.db()).unwrap().to_string();
1251     make::expr_path(make::ext::ident_path(&name))
1252 }
1253
1254 fn format_function(
1255     ctx: &AssistContext,
1256     module: hir::Module,
1257     fun: &Function,
1258     old_indent: IndentLevel,
1259     new_indent: IndentLevel,
1260 ) -> String {
1261     let mut fn_def = String::new();
1262     let params = fun.make_param_list(ctx, module);
1263     let ret_ty = fun.make_ret_ty(ctx, module);
1264     let body = make_body(ctx, old_indent, new_indent, fun);
1265     let const_kw = if fun.mods.is_const { "const " } else { "" };
1266     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
1267     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
1268     match ctx.config.snippet_cap {
1269         Some(_) => format_to!(
1270             fn_def,
1271             "\n\n{}{}{}{}fn $0{}{}",
1272             new_indent,
1273             const_kw,
1274             async_kw,
1275             unsafe_kw,
1276             fun.name,
1277             params
1278         ),
1279         None => format_to!(
1280             fn_def,
1281             "\n\n{}{}{}{}fn {}{}",
1282             new_indent,
1283             const_kw,
1284             async_kw,
1285             unsafe_kw,
1286             fun.name,
1287             params
1288         ),
1289     }
1290     if let Some(ret_ty) = ret_ty {
1291         format_to!(fn_def, " {}", ret_ty);
1292     }
1293     format_to!(fn_def, " {}", body);
1294
1295     fn_def
1296 }
1297
1298 impl Function {
1299     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
1300         let self_param = self.self_param.clone();
1301         let params = self.params.iter().map(|param| param.to_param(ctx, module));
1302         make::param_list(self_param, params)
1303     }
1304
1305     fn make_ret_ty(&self, ctx: &AssistContext, module: hir::Module) -> Option<ast::RetType> {
1306         let fun_ty = self.return_type(ctx);
1307         let handler = if self.mods.is_in_tail {
1308             FlowHandler::None
1309         } else {
1310             FlowHandler::from_ret_ty(self, &fun_ty)
1311         };
1312         let ret_ty = match &handler {
1313             FlowHandler::None => {
1314                 if matches!(fun_ty, FunType::Unit) {
1315                     return None;
1316                 }
1317                 fun_ty.make_ty(ctx, module)
1318             }
1319             FlowHandler::Try { kind: TryKind::Option } => {
1320                 make::ext::ty_option(fun_ty.make_ty(ctx, module))
1321             }
1322             FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1323                 let handler_ty = parent_ret_ty
1324                     .type_arguments()
1325                     .nth(1)
1326                     .map(|ty| make_ty(&ty, ctx, module))
1327                     .unwrap_or_else(make::ty_placeholder);
1328                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1329             }
1330             FlowHandler::If { .. } => make::ext::ty_bool(),
1331             FlowHandler::IfOption { action } => {
1332                 let handler_ty = action
1333                     .expr_ty(ctx)
1334                     .map(|ty| make_ty(&ty, ctx, module))
1335                     .unwrap_or_else(make::ty_placeholder);
1336                 make::ext::ty_option(handler_ty)
1337             }
1338             FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1339             FlowHandler::MatchResult { err } => {
1340                 let handler_ty = err
1341                     .expr_ty(ctx)
1342                     .map(|ty| make_ty(&ty, ctx, module))
1343                     .unwrap_or_else(make::ty_placeholder);
1344                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1345             }
1346         };
1347         Some(make::ret_type(ret_ty))
1348     }
1349 }
1350
1351 impl FunType {
1352     fn make_ty(&self, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1353         match self {
1354             FunType::Unit => make::ty_unit(),
1355             FunType::Single(ty) => make_ty(ty, ctx, module),
1356             FunType::Tuple(types) => match types.as_slice() {
1357                 [] => {
1358                     stdx::never!("tuple type with 0 elements");
1359                     make::ty_unit()
1360                 }
1361                 [ty] => {
1362                     stdx::never!("tuple type with 1 element");
1363                     make_ty(ty, ctx, module)
1364                 }
1365                 types => {
1366                     let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1367                     make::ty_tuple(types)
1368                 }
1369             },
1370         }
1371     }
1372 }
1373
1374 fn make_body(
1375     ctx: &AssistContext,
1376     old_indent: IndentLevel,
1377     new_indent: IndentLevel,
1378     fun: &Function,
1379 ) -> ast::BlockExpr {
1380     let ret_ty = fun.return_type(ctx);
1381     let handler = if fun.mods.is_in_tail {
1382         FlowHandler::None
1383     } else {
1384         FlowHandler::from_ret_ty(fun, &ret_ty)
1385     };
1386     let block = match &fun.body {
1387         FunctionBody::Expr(expr) => {
1388             let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1389             let expr = ast::Expr::cast(expr).unwrap();
1390             match expr {
1391                 ast::Expr::BlockExpr(block) => {
1392                     // If the extracted expression is itself a block, there is no need to wrap it inside another block.
1393                     let block = block.dedent(old_indent);
1394                     // Recreate the block for formatting consistency with other extracted functions.
1395                     make::block_expr(block.statements(), block.tail_expr())
1396                 }
1397                 _ => {
1398                     let expr = expr.dedent(old_indent).indent(IndentLevel(1));
1399
1400                     make::block_expr(Vec::new(), Some(expr))
1401                 }
1402             }
1403         }
1404         FunctionBody::Span { parent, text_range } => {
1405             let mut elements: Vec<_> = parent
1406                 .syntax()
1407                 .children()
1408                 .filter(|it| text_range.contains_range(it.text_range()))
1409                 .map(|it| rewrite_body_segment(ctx, &fun.params, &handler, &it))
1410                 .collect();
1411
1412             let mut tail_expr = match elements.pop() {
1413                 Some(node) => ast::Expr::cast(node.clone()).or_else(|| {
1414                     elements.push(node);
1415                     None
1416                 }),
1417                 None => None,
1418             };
1419
1420             if tail_expr.is_none() {
1421                 match fun.outliving_locals.as_slice() {
1422                     [] => {}
1423                     [var] => {
1424                         tail_expr = Some(path_expr_from_local(ctx, var.local));
1425                     }
1426                     vars => {
1427                         let exprs = vars.iter().map(|var| path_expr_from_local(ctx, var.local));
1428                         let expr = make::expr_tuple(exprs);
1429                         tail_expr = Some(expr);
1430                     }
1431                 }
1432             }
1433
1434             let elements = elements.into_iter().filter_map(|node| match ast::Stmt::cast(node) {
1435                 Some(stmt) => Some(stmt),
1436                 None => {
1437                     stdx::never!("block contains non-statement");
1438                     None
1439                 }
1440             });
1441
1442             let body_indent = IndentLevel(1);
1443             let elements = elements.map(|stmt| stmt.dedent(old_indent).indent(body_indent));
1444             let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
1445
1446             make::block_expr(elements, tail_expr)
1447         }
1448     };
1449
1450     let block = match &handler {
1451         FlowHandler::None => block,
1452         FlowHandler::Try { kind } => {
1453             let block = with_default_tail_expr(block, make::expr_unit());
1454             map_tail_expr(block, |tail_expr| {
1455                 let constructor = match kind {
1456                     TryKind::Option => "Some",
1457                     TryKind::Result { .. } => "Ok",
1458                 };
1459                 let func = make::expr_path(make::ext::ident_path(constructor));
1460                 let args = make::arg_list(iter::once(tail_expr));
1461                 make::expr_call(func, args)
1462             })
1463         }
1464         FlowHandler::If { .. } => {
1465             let lit_false = make::expr_literal("false");
1466             with_tail_expr(block, lit_false.into())
1467         }
1468         FlowHandler::IfOption { .. } => {
1469             let none = make::expr_path(make::ext::ident_path("None"));
1470             with_tail_expr(block, none)
1471         }
1472         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1473             let some = make::expr_path(make::ext::ident_path("Some"));
1474             let args = make::arg_list(iter::once(tail_expr));
1475             make::expr_call(some, args)
1476         }),
1477         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1478             let ok = make::expr_path(make::ext::ident_path("Ok"));
1479             let args = make::arg_list(iter::once(tail_expr));
1480             make::expr_call(ok, args)
1481         }),
1482     };
1483
1484     block.indent(new_indent)
1485 }
1486
1487 fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1488     let tail_expr = match block.tail_expr() {
1489         Some(tail_expr) => tail_expr,
1490         None => return block,
1491     };
1492     make::block_expr(block.statements(), Some(f(tail_expr)))
1493 }
1494
1495 fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1496     match block.tail_expr() {
1497         Some(_) => block,
1498         None => make::block_expr(block.statements(), Some(tail_expr)),
1499     }
1500 }
1501
1502 fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1503     let stmt_tail = block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1504     let stmts = block.statements().chain(stmt_tail);
1505     make::block_expr(stmts, Some(tail_expr))
1506 }
1507
1508 fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String {
1509     ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string())
1510 }
1511
1512 fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1513     let ty_str = format_type(ty, ctx, module);
1514     make::ty(&ty_str)
1515 }
1516
1517 fn rewrite_body_segment(
1518     ctx: &AssistContext,
1519     params: &[Param],
1520     handler: &FlowHandler,
1521     syntax: &SyntaxNode,
1522 ) -> SyntaxNode {
1523     let syntax = fix_param_usages(ctx, params, syntax);
1524     update_external_control_flow(handler, &syntax);
1525     syntax
1526 }
1527
1528 /// change all usages to account for added `&`/`&mut` for some params
1529 fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode {
1530     let mut usages_for_param: Vec<(&Param, Vec<ast::Expr>)> = Vec::new();
1531
1532     let tm = TreeMutator::new(syntax);
1533
1534     for param in params {
1535         if !param.kind().is_ref() {
1536             continue;
1537         }
1538
1539         let usages = LocalUsages::find_local_usages(ctx, param.var);
1540         let usages = usages
1541             .iter()
1542             .filter(|reference| syntax.text_range().contains_range(reference.range))
1543             .filter_map(|reference| path_element_of_reference(syntax, reference))
1544             .map(|expr| tm.make_mut(&expr));
1545
1546         usages_for_param.push((param, usages.collect()));
1547     }
1548
1549     let res = tm.make_syntax_mut(syntax);
1550
1551     for (param, usages) in usages_for_param {
1552         for usage in usages {
1553             match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
1554                 Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
1555                     // do nothing
1556                 }
1557                 Some(ast::Expr::RefExpr(node))
1558                     if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
1559                 {
1560                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1561                 }
1562                 Some(ast::Expr::RefExpr(node))
1563                     if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
1564                 {
1565                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1566                 }
1567                 Some(_) | None => {
1568                     let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update();
1569                     ted::replace(usage.syntax(), p.syntax())
1570                 }
1571             }
1572         }
1573     }
1574
1575     res
1576 }
1577
1578 fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) {
1579     let mut nested_loop = None;
1580     let mut nested_scope = None;
1581     for event in syntax.preorder() {
1582         match event {
1583             WalkEvent::Enter(e) => match e.kind() {
1584                 SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
1585                     if nested_loop.is_none() {
1586                         nested_loop = Some(e.clone());
1587                     }
1588                 }
1589                 SyntaxKind::FN
1590                 | SyntaxKind::CONST
1591                 | SyntaxKind::STATIC
1592                 | SyntaxKind::IMPL
1593                 | SyntaxKind::MODULE => {
1594                     if nested_scope.is_none() {
1595                         nested_scope = Some(e.clone());
1596                     }
1597                 }
1598                 _ => {}
1599             },
1600             WalkEvent::Leave(e) => {
1601                 if nested_scope.is_none() {
1602                     if let Some(expr) = ast::Expr::cast(e.clone()) {
1603                         match expr {
1604                             ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => {
1605                                 let expr = return_expr.expr();
1606                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1607                                     ted::replace(return_expr.syntax(), replacement.syntax())
1608                                 }
1609                             }
1610                             ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
1611                                 let expr = break_expr.expr();
1612                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1613                                     ted::replace(break_expr.syntax(), replacement.syntax())
1614                                 }
1615                             }
1616                             ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
1617                                 if let Some(replacement) = make_rewritten_flow(handler, None) {
1618                                     ted::replace(continue_expr.syntax(), replacement.syntax())
1619                                 }
1620                             }
1621                             _ => {
1622                                 // do nothing
1623                             }
1624                         }
1625                     }
1626                 }
1627
1628                 if nested_loop.as_ref() == Some(&e) {
1629                     nested_loop = None;
1630                 }
1631                 if nested_scope.as_ref() == Some(&e) {
1632                     nested_scope = None;
1633                 }
1634             }
1635         };
1636     }
1637 }
1638
1639 fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1640     let value = match handler {
1641         FlowHandler::None | FlowHandler::Try { .. } => return None,
1642         FlowHandler::If { .. } => make::expr_literal("true").into(),
1643         FlowHandler::IfOption { .. } => {
1644             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1645             let args = make::arg_list(iter::once(expr));
1646             make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
1647         }
1648         FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
1649         FlowHandler::MatchResult { .. } => {
1650             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1651             let args = make::arg_list(iter::once(expr));
1652             make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
1653         }
1654     };
1655     Some(make::expr_return(Some(value)).clone_for_update())
1656 }
1657
1658 #[cfg(test)]
1659 mod tests {
1660     use crate::tests::{check_assist, check_assist_not_applicable};
1661
1662     use super::*;
1663
1664     #[test]
1665     fn no_args_from_binary_expr() {
1666         check_assist(
1667             extract_function,
1668             r#"
1669 fn foo() {
1670     foo($01 + 1$0);
1671 }
1672 "#,
1673             r#"
1674 fn foo() {
1675     foo(fun_name());
1676 }
1677
1678 fn $0fun_name() -> i32 {
1679     1 + 1
1680 }
1681 "#,
1682         );
1683     }
1684
1685     #[test]
1686     fn no_args_from_binary_expr_in_module() {
1687         check_assist(
1688             extract_function,
1689             r#"
1690 mod bar {
1691     fn foo() {
1692         foo($01 + 1$0);
1693     }
1694 }
1695 "#,
1696             r#"
1697 mod bar {
1698     fn foo() {
1699         foo(fun_name());
1700     }
1701
1702     fn $0fun_name() -> i32 {
1703         1 + 1
1704     }
1705 }
1706 "#,
1707         );
1708     }
1709
1710     #[test]
1711     fn no_args_from_binary_expr_indented() {
1712         check_assist(
1713             extract_function,
1714             r#"
1715 fn foo() {
1716     $0{ 1 + 1 }$0;
1717 }
1718 "#,
1719             r#"
1720 fn foo() {
1721     fun_name();
1722 }
1723
1724 fn $0fun_name() -> i32 {
1725     1 + 1
1726 }
1727 "#,
1728         );
1729     }
1730
1731     #[test]
1732     fn no_args_from_stmt_with_last_expr() {
1733         check_assist(
1734             extract_function,
1735             r#"
1736 fn foo() -> i32 {
1737     let k = 1;
1738     $0let m = 1;
1739     m + 1$0
1740 }
1741 "#,
1742             r#"
1743 fn foo() -> i32 {
1744     let k = 1;
1745     fun_name()
1746 }
1747
1748 fn $0fun_name() -> i32 {
1749     let m = 1;
1750     m + 1
1751 }
1752 "#,
1753         );
1754     }
1755
1756     #[test]
1757     fn no_args_from_stmt_unit() {
1758         check_assist(
1759             extract_function,
1760             r#"
1761 fn foo() {
1762     let k = 3;
1763     $0let m = 1;
1764     let n = m + 1;$0
1765     let g = 5;
1766 }
1767 "#,
1768             r#"
1769 fn foo() {
1770     let k = 3;
1771     fun_name();
1772     let g = 5;
1773 }
1774
1775 fn $0fun_name() {
1776     let m = 1;
1777     let n = m + 1;
1778 }
1779 "#,
1780         );
1781     }
1782
1783     #[test]
1784     fn no_args_if() {
1785         check_assist(
1786             extract_function,
1787             r#"
1788 fn foo() {
1789     $0if true { }$0
1790 }
1791 "#,
1792             r#"
1793 fn foo() {
1794     fun_name();
1795 }
1796
1797 fn $0fun_name() {
1798     if true { }
1799 }
1800 "#,
1801         );
1802     }
1803
1804     #[test]
1805     fn no_args_if_else() {
1806         check_assist(
1807             extract_function,
1808             r#"
1809 fn foo() -> i32 {
1810     $0if true { 1 } else { 2 }$0
1811 }
1812 "#,
1813             r#"
1814 fn foo() -> i32 {
1815     fun_name()
1816 }
1817
1818 fn $0fun_name() -> i32 {
1819     if true { 1 } else { 2 }
1820 }
1821 "#,
1822         );
1823     }
1824
1825     #[test]
1826     fn no_args_if_let_else() {
1827         check_assist(
1828             extract_function,
1829             r#"
1830 fn foo() -> i32 {
1831     $0if let true = false { 1 } else { 2 }$0
1832 }
1833 "#,
1834             r#"
1835 fn foo() -> i32 {
1836     fun_name()
1837 }
1838
1839 fn $0fun_name() -> i32 {
1840     if let true = false { 1 } else { 2 }
1841 }
1842 "#,
1843         );
1844     }
1845
1846     #[test]
1847     fn no_args_match() {
1848         check_assist(
1849             extract_function,
1850             r#"
1851 fn foo() -> i32 {
1852     $0match true {
1853         true => 1,
1854         false => 2,
1855     }$0
1856 }
1857 "#,
1858             r#"
1859 fn foo() -> i32 {
1860     fun_name()
1861 }
1862
1863 fn $0fun_name() -> i32 {
1864     match true {
1865         true => 1,
1866         false => 2,
1867     }
1868 }
1869 "#,
1870         );
1871     }
1872
1873     #[test]
1874     fn no_args_while() {
1875         check_assist(
1876             extract_function,
1877             r#"
1878 fn foo() {
1879     $0while true { }$0
1880 }
1881 "#,
1882             r#"
1883 fn foo() {
1884     fun_name();
1885 }
1886
1887 fn $0fun_name() {
1888     while true { }
1889 }
1890 "#,
1891         );
1892     }
1893
1894     #[test]
1895     fn no_args_for() {
1896         check_assist(
1897             extract_function,
1898             r#"
1899 fn foo() {
1900     $0for v in &[0, 1] { }$0
1901 }
1902 "#,
1903             r#"
1904 fn foo() {
1905     fun_name();
1906 }
1907
1908 fn $0fun_name() {
1909     for v in &[0, 1] { }
1910 }
1911 "#,
1912         );
1913     }
1914
1915     #[test]
1916     fn no_args_from_loop_unit() {
1917         check_assist(
1918             extract_function,
1919             r#"
1920 fn foo() {
1921     $0loop {
1922         let m = 1;
1923     }$0
1924 }
1925 "#,
1926             r#"
1927 fn foo() {
1928     fun_name()
1929 }
1930
1931 fn $0fun_name() -> ! {
1932     loop {
1933         let m = 1;
1934     }
1935 }
1936 "#,
1937         );
1938     }
1939
1940     #[test]
1941     fn no_args_from_loop_with_return() {
1942         check_assist(
1943             extract_function,
1944             r#"
1945 fn foo() {
1946     let v = $0loop {
1947         let m = 1;
1948         break m;
1949     }$0;
1950 }
1951 "#,
1952             r#"
1953 fn foo() {
1954     let v = fun_name();
1955 }
1956
1957 fn $0fun_name() -> i32 {
1958     loop {
1959         let m = 1;
1960         break m;
1961     }
1962 }
1963 "#,
1964         );
1965     }
1966
1967     #[test]
1968     fn no_args_from_match() {
1969         check_assist(
1970             extract_function,
1971             r#"
1972 fn foo() {
1973     let v: i32 = $0match Some(1) {
1974         Some(x) => x,
1975         None => 0,
1976     }$0;
1977 }
1978 "#,
1979             r#"
1980 fn foo() {
1981     let v: i32 = fun_name();
1982 }
1983
1984 fn $0fun_name() -> i32 {
1985     match Some(1) {
1986         Some(x) => x,
1987         None => 0,
1988     }
1989 }
1990 "#,
1991         );
1992     }
1993
1994     #[test]
1995     fn extract_partial_block_single_line() {
1996         check_assist(
1997             extract_function,
1998             r#"
1999 fn foo() {
2000     let n = 1;
2001     let mut v = $0n * n;$0
2002     v += 1;
2003 }
2004 "#,
2005             r#"
2006 fn foo() {
2007     let n = 1;
2008     let mut v = fun_name(n);
2009     v += 1;
2010 }
2011
2012 fn $0fun_name(n: i32) -> i32 {
2013     let mut v = n * n;
2014     v
2015 }
2016 "#,
2017         );
2018     }
2019
2020     #[test]
2021     fn extract_partial_block() {
2022         check_assist(
2023             extract_function,
2024             r#"
2025 fn foo() {
2026     let m = 2;
2027     let n = 1;
2028     let mut v = m $0* n;
2029     let mut w = 3;$0
2030     v += 1;
2031     w += 1;
2032 }
2033 "#,
2034             r#"
2035 fn foo() {
2036     let m = 2;
2037     let n = 1;
2038     let (mut v, mut w) = fun_name(m, n);
2039     v += 1;
2040     w += 1;
2041 }
2042
2043 fn $0fun_name(m: i32, n: i32) -> (i32, i32) {
2044     let mut v = m * n;
2045     let mut w = 3;
2046     (v, w)
2047 }
2048 "#,
2049         );
2050     }
2051
2052     #[test]
2053     fn argument_form_expr() {
2054         check_assist(
2055             extract_function,
2056             r#"
2057 fn foo() -> u32 {
2058     let n = 2;
2059     $0n+2$0
2060 }
2061 "#,
2062             r#"
2063 fn foo() -> u32 {
2064     let n = 2;
2065     fun_name(n)
2066 }
2067
2068 fn $0fun_name(n: u32) -> u32 {
2069     n+2
2070 }
2071 "#,
2072         )
2073     }
2074
2075     #[test]
2076     fn argument_used_twice_form_expr() {
2077         check_assist(
2078             extract_function,
2079             r#"
2080 fn foo() -> u32 {
2081     let n = 2;
2082     $0n+n$0
2083 }
2084 "#,
2085             r#"
2086 fn foo() -> u32 {
2087     let n = 2;
2088     fun_name(n)
2089 }
2090
2091 fn $0fun_name(n: u32) -> u32 {
2092     n+n
2093 }
2094 "#,
2095         )
2096     }
2097
2098     #[test]
2099     fn two_arguments_form_expr() {
2100         check_assist(
2101             extract_function,
2102             r#"
2103 fn foo() -> u32 {
2104     let n = 2;
2105     let m = 3;
2106     $0n+n*m$0
2107 }
2108 "#,
2109             r#"
2110 fn foo() -> u32 {
2111     let n = 2;
2112     let m = 3;
2113     fun_name(n, m)
2114 }
2115
2116 fn $0fun_name(n: u32, m: u32) -> u32 {
2117     n+n*m
2118 }
2119 "#,
2120         )
2121     }
2122
2123     #[test]
2124     fn argument_and_locals() {
2125         check_assist(
2126             extract_function,
2127             r#"
2128 fn foo() -> u32 {
2129     let n = 2;
2130     $0let m = 1;
2131     n + m$0
2132 }
2133 "#,
2134             r#"
2135 fn foo() -> u32 {
2136     let n = 2;
2137     fun_name(n)
2138 }
2139
2140 fn $0fun_name(n: u32) -> u32 {
2141     let m = 1;
2142     n + m
2143 }
2144 "#,
2145         )
2146     }
2147
2148     #[test]
2149     fn in_comment_is_not_applicable() {
2150         cov_mark::check!(extract_function_in_comment_is_not_applicable);
2151         check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
2152     }
2153
2154     #[test]
2155     fn part_of_expr_stmt() {
2156         check_assist(
2157             extract_function,
2158             r#"
2159 fn foo() {
2160     $01$0 + 1;
2161 }
2162 "#,
2163             r#"
2164 fn foo() {
2165     fun_name() + 1;
2166 }
2167
2168 fn $0fun_name() -> i32 {
2169     1
2170 }
2171 "#,
2172         );
2173     }
2174
2175     #[test]
2176     fn function_expr() {
2177         check_assist(
2178             extract_function,
2179             r#"
2180 fn foo() {
2181     $0bar(1 + 1)$0
2182 }
2183 "#,
2184             r#"
2185 fn foo() {
2186     fun_name();
2187 }
2188
2189 fn $0fun_name() {
2190     bar(1 + 1)
2191 }
2192 "#,
2193         )
2194     }
2195
2196     #[test]
2197     fn extract_from_nested() {
2198         check_assist(
2199             extract_function,
2200             r#"
2201 fn main() {
2202     let x = true;
2203     let tuple = match x {
2204         true => ($02 + 2$0, true)
2205         _ => (0, false)
2206     };
2207 }
2208 "#,
2209             r#"
2210 fn main() {
2211     let x = true;
2212     let tuple = match x {
2213         true => (fun_name(), true)
2214         _ => (0, false)
2215     };
2216 }
2217
2218 fn $0fun_name() -> i32 {
2219     2 + 2
2220 }
2221 "#,
2222         );
2223     }
2224
2225     #[test]
2226     fn param_from_closure() {
2227         check_assist(
2228             extract_function,
2229             r#"
2230 fn main() {
2231     let lambda = |x: u32| $0x * 2$0;
2232 }
2233 "#,
2234             r#"
2235 fn main() {
2236     let lambda = |x: u32| fun_name(x);
2237 }
2238
2239 fn $0fun_name(x: u32) -> u32 {
2240     x * 2
2241 }
2242 "#,
2243         );
2244     }
2245
2246     #[test]
2247     fn extract_return_stmt() {
2248         check_assist(
2249             extract_function,
2250             r#"
2251 fn foo() -> u32 {
2252     $0return 2 + 2$0;
2253 }
2254 "#,
2255             r#"
2256 fn foo() -> u32 {
2257     return fun_name();
2258 }
2259
2260 fn $0fun_name() -> u32 {
2261     2 + 2
2262 }
2263 "#,
2264         );
2265     }
2266
2267     #[test]
2268     fn does_not_add_extra_whitespace() {
2269         check_assist(
2270             extract_function,
2271             r#"
2272 fn foo() -> u32 {
2273
2274
2275     $0return 2 + 2$0;
2276 }
2277 "#,
2278             r#"
2279 fn foo() -> u32 {
2280
2281
2282     return fun_name();
2283 }
2284
2285 fn $0fun_name() -> u32 {
2286     2 + 2
2287 }
2288 "#,
2289         );
2290     }
2291
2292     #[test]
2293     fn break_stmt() {
2294         check_assist(
2295             extract_function,
2296             r#"
2297 fn main() {
2298     let result = loop {
2299         $0break 2 + 2$0;
2300     };
2301 }
2302 "#,
2303             r#"
2304 fn main() {
2305     let result = loop {
2306         break fun_name();
2307     };
2308 }
2309
2310 fn $0fun_name() -> i32 {
2311     2 + 2
2312 }
2313 "#,
2314         );
2315     }
2316
2317     #[test]
2318     fn extract_cast() {
2319         check_assist(
2320             extract_function,
2321             r#"
2322 fn main() {
2323     let v = $00f32 as u32$0;
2324 }
2325 "#,
2326             r#"
2327 fn main() {
2328     let v = fun_name();
2329 }
2330
2331 fn $0fun_name() -> u32 {
2332     0f32 as u32
2333 }
2334 "#,
2335         );
2336     }
2337
2338     #[test]
2339     fn return_not_applicable() {
2340         check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2341     }
2342
2343     #[test]
2344     fn method_to_freestanding() {
2345         check_assist(
2346             extract_function,
2347             r#"
2348 struct S;
2349
2350 impl S {
2351     fn foo(&self) -> i32 {
2352         $01+1$0
2353     }
2354 }
2355 "#,
2356             r#"
2357 struct S;
2358
2359 impl S {
2360     fn foo(&self) -> i32 {
2361         fun_name()
2362     }
2363 }
2364
2365 fn $0fun_name() -> i32 {
2366     1+1
2367 }
2368 "#,
2369         );
2370     }
2371
2372     #[test]
2373     fn method_with_reference() {
2374         check_assist(
2375             extract_function,
2376             r#"
2377 struct S { f: i32 };
2378
2379 impl S {
2380     fn foo(&self) -> i32 {
2381         $0self.f+self.f$0
2382     }
2383 }
2384 "#,
2385             r#"
2386 struct S { f: i32 };
2387
2388 impl S {
2389     fn foo(&self) -> i32 {
2390         self.fun_name()
2391     }
2392
2393     fn $0fun_name(&self) -> i32 {
2394         self.f+self.f
2395     }
2396 }
2397 "#,
2398         );
2399     }
2400
2401     #[test]
2402     fn method_with_mut() {
2403         check_assist(
2404             extract_function,
2405             r#"
2406 struct S { f: i32 };
2407
2408 impl S {
2409     fn foo(&mut self) {
2410         $0self.f += 1;$0
2411     }
2412 }
2413 "#,
2414             r#"
2415 struct S { f: i32 };
2416
2417 impl S {
2418     fn foo(&mut self) {
2419         self.fun_name();
2420     }
2421
2422     fn $0fun_name(&mut self) {
2423         self.f += 1;
2424     }
2425 }
2426 "#,
2427         );
2428     }
2429
2430     #[test]
2431     fn variable_defined_inside_and_used_after_no_ret() {
2432         check_assist(
2433             extract_function,
2434             r#"
2435 fn foo() {
2436     let n = 1;
2437     $0let k = n * n;$0
2438     let m = k + 1;
2439 }
2440 "#,
2441             r#"
2442 fn foo() {
2443     let n = 1;
2444     let k = fun_name(n);
2445     let m = k + 1;
2446 }
2447
2448 fn $0fun_name(n: i32) -> i32 {
2449     let k = n * n;
2450     k
2451 }
2452 "#,
2453         );
2454     }
2455
2456     #[test]
2457     fn variable_defined_inside_and_used_after_mutably_no_ret() {
2458         check_assist(
2459             extract_function,
2460             r#"
2461 fn foo() {
2462     let n = 1;
2463     $0let mut k = n * n;$0
2464     k += 1;
2465 }
2466 "#,
2467             r#"
2468 fn foo() {
2469     let n = 1;
2470     let mut k = fun_name(n);
2471     k += 1;
2472 }
2473
2474 fn $0fun_name(n: i32) -> i32 {
2475     let mut k = n * n;
2476     k
2477 }
2478 "#,
2479         );
2480     }
2481
2482     #[test]
2483     fn two_variables_defined_inside_and_used_after_no_ret() {
2484         check_assist(
2485             extract_function,
2486             r#"
2487 fn foo() {
2488     let n = 1;
2489     $0let k = n * n;
2490     let m = k + 2;$0
2491     let h = k + m;
2492 }
2493 "#,
2494             r#"
2495 fn foo() {
2496     let n = 1;
2497     let (k, m) = fun_name(n);
2498     let h = k + m;
2499 }
2500
2501 fn $0fun_name(n: i32) -> (i32, i32) {
2502     let k = n * n;
2503     let m = k + 2;
2504     (k, m)
2505 }
2506 "#,
2507         );
2508     }
2509
2510     #[test]
2511     fn multi_variables_defined_inside_and_used_after_mutably_no_ret() {
2512         check_assist(
2513             extract_function,
2514             r#"
2515 fn foo() {
2516     let n = 1;
2517     $0let mut k = n * n;
2518     let mut m = k + 2;
2519     let mut o = m + 3;
2520     o += 1;$0
2521     k += o;
2522     m = 1;
2523 }
2524 "#,
2525             r#"
2526 fn foo() {
2527     let n = 1;
2528     let (mut k, mut m, o) = fun_name(n);
2529     k += o;
2530     m = 1;
2531 }
2532
2533 fn $0fun_name(n: i32) -> (i32, i32, i32) {
2534     let mut k = n * n;
2535     let mut m = k + 2;
2536     let mut o = m + 3;
2537     o += 1;
2538     (k, m, o)
2539 }
2540 "#,
2541         );
2542     }
2543
2544     #[test]
2545     fn nontrivial_patterns_define_variables() {
2546         check_assist(
2547             extract_function,
2548             r#"
2549 struct Counter(i32);
2550 fn foo() {
2551     $0let Counter(n) = Counter(0);$0
2552     let m = n;
2553 }
2554 "#,
2555             r#"
2556 struct Counter(i32);
2557 fn foo() {
2558     let n = fun_name();
2559     let m = n;
2560 }
2561
2562 fn $0fun_name() -> i32 {
2563     let Counter(n) = Counter(0);
2564     n
2565 }
2566 "#,
2567         );
2568     }
2569
2570     #[test]
2571     fn struct_with_two_fields_pattern_define_variables() {
2572         check_assist(
2573             extract_function,
2574             r#"
2575 struct Counter { n: i32, m: i32 };
2576 fn foo() {
2577     $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
2578     let h = n + k;
2579 }
2580 "#,
2581             r#"
2582 struct Counter { n: i32, m: i32 };
2583 fn foo() {
2584     let (n, k) = fun_name();
2585     let h = n + k;
2586 }
2587
2588 fn $0fun_name() -> (i32, i32) {
2589     let Counter { n, m: k } = Counter { n: 1, m: 2 };
2590     (n, k)
2591 }
2592 "#,
2593         );
2594     }
2595
2596     #[test]
2597     fn mut_var_from_outer_scope() {
2598         check_assist(
2599             extract_function,
2600             r#"
2601 fn foo() {
2602     let mut n = 1;
2603     $0n += 1;$0
2604     let m = n + 1;
2605 }
2606 "#,
2607             r#"
2608 fn foo() {
2609     let mut n = 1;
2610     fun_name(&mut n);
2611     let m = n + 1;
2612 }
2613
2614 fn $0fun_name(n: &mut i32) {
2615     *n += 1;
2616 }
2617 "#,
2618         );
2619     }
2620
2621     #[test]
2622     fn mut_field_from_outer_scope() {
2623         check_assist(
2624             extract_function,
2625             r#"
2626 struct C { n: i32 }
2627 fn foo() {
2628     let mut c = C { n: 0 };
2629     $0c.n += 1;$0
2630     let m = c.n + 1;
2631 }
2632 "#,
2633             r#"
2634 struct C { n: i32 }
2635 fn foo() {
2636     let mut c = C { n: 0 };
2637     fun_name(&mut c);
2638     let m = c.n + 1;
2639 }
2640
2641 fn $0fun_name(c: &mut C) {
2642     c.n += 1;
2643 }
2644 "#,
2645         );
2646     }
2647
2648     #[test]
2649     fn mut_nested_field_from_outer_scope() {
2650         check_assist(
2651             extract_function,
2652             r#"
2653 struct P { n: i32}
2654 struct C { p: P }
2655 fn foo() {
2656     let mut c = C { p: P { n: 0 } };
2657     let mut v = C { p: P { n: 0 } };
2658     let u = C { p: P { n: 0 } };
2659     $0c.p.n += u.p.n;
2660     let r = &mut v.p.n;$0
2661     let m = c.p.n + v.p.n + u.p.n;
2662 }
2663 "#,
2664             r#"
2665 struct P { n: i32}
2666 struct C { p: P }
2667 fn foo() {
2668     let mut c = C { p: P { n: 0 } };
2669     let mut v = C { p: P { n: 0 } };
2670     let u = C { p: P { n: 0 } };
2671     fun_name(&mut c, &u, &mut v);
2672     let m = c.p.n + v.p.n + u.p.n;
2673 }
2674
2675 fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
2676     c.p.n += u.p.n;
2677     let r = &mut v.p.n;
2678 }
2679 "#,
2680         );
2681     }
2682
2683     #[test]
2684     fn mut_param_many_usages_stmt() {
2685         check_assist(
2686             extract_function,
2687             r#"
2688 fn bar(k: i32) {}
2689 trait I: Copy {
2690     fn succ(&self) -> Self;
2691     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2692 }
2693 impl I for i32 {
2694     fn succ(&self) -> Self { *self + 1 }
2695 }
2696 fn foo() {
2697     let mut n = 1;
2698     $0n += n;
2699     bar(n);
2700     bar(n+1);
2701     bar(n*n);
2702     bar(&n);
2703     n.inc();
2704     let v = &mut n;
2705     *v = v.succ();
2706     n.succ();$0
2707     let m = n + 1;
2708 }
2709 "#,
2710             r#"
2711 fn bar(k: i32) {}
2712 trait I: Copy {
2713     fn succ(&self) -> Self;
2714     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2715 }
2716 impl I for i32 {
2717     fn succ(&self) -> Self { *self + 1 }
2718 }
2719 fn foo() {
2720     let mut n = 1;
2721     fun_name(&mut n);
2722     let m = n + 1;
2723 }
2724
2725 fn $0fun_name(n: &mut i32) {
2726     *n += *n;
2727     bar(*n);
2728     bar(*n+1);
2729     bar(*n**n);
2730     bar(&*n);
2731     n.inc();
2732     let v = n;
2733     *v = v.succ();
2734     n.succ();
2735 }
2736 "#,
2737         );
2738     }
2739
2740     #[test]
2741     fn mut_param_many_usages_expr() {
2742         check_assist(
2743             extract_function,
2744             r#"
2745 fn bar(k: i32) {}
2746 trait I: Copy {
2747     fn succ(&self) -> Self;
2748     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2749 }
2750 impl I for i32 {
2751     fn succ(&self) -> Self { *self + 1 }
2752 }
2753 fn foo() {
2754     let mut n = 1;
2755     $0{
2756         n += n;
2757         bar(n);
2758         bar(n+1);
2759         bar(n*n);
2760         bar(&n);
2761         n.inc();
2762         let v = &mut n;
2763         *v = v.succ();
2764         n.succ();
2765     }$0
2766     let m = n + 1;
2767 }
2768 "#,
2769             r#"
2770 fn bar(k: i32) {}
2771 trait I: Copy {
2772     fn succ(&self) -> Self;
2773     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2774 }
2775 impl I for i32 {
2776     fn succ(&self) -> Self { *self + 1 }
2777 }
2778 fn foo() {
2779     let mut n = 1;
2780     fun_name(&mut n);
2781     let m = n + 1;
2782 }
2783
2784 fn $0fun_name(n: &mut i32) {
2785     *n += *n;
2786     bar(*n);
2787     bar(*n+1);
2788     bar(*n**n);
2789     bar(&*n);
2790     n.inc();
2791     let v = n;
2792     *v = v.succ();
2793     n.succ();
2794 }
2795 "#,
2796         );
2797     }
2798
2799     #[test]
2800     fn mut_param_by_value() {
2801         check_assist(
2802             extract_function,
2803             r#"
2804 fn foo() {
2805     let mut n = 1;
2806     $0n += 1;$0
2807 }
2808 "#,
2809             r"
2810 fn foo() {
2811     let mut n = 1;
2812     fun_name(n);
2813 }
2814
2815 fn $0fun_name(mut n: i32) {
2816     n += 1;
2817 }
2818 ",
2819         );
2820     }
2821
2822     #[test]
2823     fn mut_param_because_of_mut_ref() {
2824         check_assist(
2825             extract_function,
2826             r#"
2827 fn foo() {
2828     let mut n = 1;
2829     $0let v = &mut n;
2830     *v += 1;$0
2831     let k = n;
2832 }
2833 "#,
2834             r#"
2835 fn foo() {
2836     let mut n = 1;
2837     fun_name(&mut n);
2838     let k = n;
2839 }
2840
2841 fn $0fun_name(n: &mut i32) {
2842     let v = n;
2843     *v += 1;
2844 }
2845 "#,
2846         );
2847     }
2848
2849     #[test]
2850     fn mut_param_by_value_because_of_mut_ref() {
2851         check_assist(
2852             extract_function,
2853             r"
2854 fn foo() {
2855     let mut n = 1;
2856     $0let v = &mut n;
2857     *v += 1;$0
2858 }
2859 ",
2860             r#"
2861 fn foo() {
2862     let mut n = 1;
2863     fun_name(n);
2864 }
2865
2866 fn $0fun_name(mut n: i32) {
2867     let v = &mut n;
2868     *v += 1;
2869 }
2870 "#,
2871         );
2872     }
2873
2874     #[test]
2875     fn mut_method_call() {
2876         check_assist(
2877             extract_function,
2878             r#"
2879 trait I {
2880     fn inc(&mut self);
2881 }
2882 impl I for i32 {
2883     fn inc(&mut self) { *self += 1 }
2884 }
2885 fn foo() {
2886     let mut n = 1;
2887     $0n.inc();$0
2888 }
2889 "#,
2890             r#"
2891 trait I {
2892     fn inc(&mut self);
2893 }
2894 impl I for i32 {
2895     fn inc(&mut self) { *self += 1 }
2896 }
2897 fn foo() {
2898     let mut n = 1;
2899     fun_name(n);
2900 }
2901
2902 fn $0fun_name(mut n: i32) {
2903     n.inc();
2904 }
2905 "#,
2906         );
2907     }
2908
2909     #[test]
2910     fn shared_method_call() {
2911         check_assist(
2912             extract_function,
2913             r#"
2914 trait I {
2915     fn succ(&self);
2916 }
2917 impl I for i32 {
2918     fn succ(&self) { *self + 1 }
2919 }
2920 fn foo() {
2921     let mut n = 1;
2922     $0n.succ();$0
2923 }
2924 "#,
2925             r"
2926 trait I {
2927     fn succ(&self);
2928 }
2929 impl I for i32 {
2930     fn succ(&self) { *self + 1 }
2931 }
2932 fn foo() {
2933     let mut n = 1;
2934     fun_name(n);
2935 }
2936
2937 fn $0fun_name(n: i32) {
2938     n.succ();
2939 }
2940 ",
2941         );
2942     }
2943
2944     #[test]
2945     fn mut_method_call_with_other_receiver() {
2946         check_assist(
2947             extract_function,
2948             r#"
2949 trait I {
2950     fn inc(&mut self, n: i32);
2951 }
2952 impl I for i32 {
2953     fn inc(&mut self, n: i32) { *self += n }
2954 }
2955 fn foo() {
2956     let mut n = 1;
2957     $0let mut m = 2;
2958     m.inc(n);$0
2959 }
2960 "#,
2961             r"
2962 trait I {
2963     fn inc(&mut self, n: i32);
2964 }
2965 impl I for i32 {
2966     fn inc(&mut self, n: i32) { *self += n }
2967 }
2968 fn foo() {
2969     let mut n = 1;
2970     fun_name(n);
2971 }
2972
2973 fn $0fun_name(n: i32) {
2974     let mut m = 2;
2975     m.inc(n);
2976 }
2977 ",
2978         );
2979     }
2980
2981     #[test]
2982     fn non_copy_without_usages_after() {
2983         check_assist(
2984             extract_function,
2985             r#"
2986 struct Counter(i32);
2987 fn foo() {
2988     let c = Counter(0);
2989     $0let n = c.0;$0
2990 }
2991 "#,
2992             r"
2993 struct Counter(i32);
2994 fn foo() {
2995     let c = Counter(0);
2996     fun_name(c);
2997 }
2998
2999 fn $0fun_name(c: Counter) {
3000     let n = c.0;
3001 }
3002 ",
3003         );
3004     }
3005
3006     #[test]
3007     fn non_copy_used_after() {
3008         check_assist(
3009             extract_function,
3010             r"
3011 struct Counter(i32);
3012 fn foo() {
3013     let c = Counter(0);
3014     $0let n = c.0;$0
3015     let m = c.0;
3016 }
3017 ",
3018             r#"
3019 struct Counter(i32);
3020 fn foo() {
3021     let c = Counter(0);
3022     fun_name(&c);
3023     let m = c.0;
3024 }
3025
3026 fn $0fun_name(c: &Counter) {
3027     let n = c.0;
3028 }
3029 "#,
3030         );
3031     }
3032
3033     #[test]
3034     fn copy_used_after() {
3035         check_assist(
3036             extract_function,
3037             r#"
3038 //- minicore: copy
3039 fn foo() {
3040     let n = 0;
3041     $0let m = n;$0
3042     let k = n;
3043 }
3044 "#,
3045             r#"
3046 fn foo() {
3047     let n = 0;
3048     fun_name(n);
3049     let k = n;
3050 }
3051
3052 fn $0fun_name(n: i32) {
3053     let m = n;
3054 }
3055 "#,
3056         )
3057     }
3058
3059     #[test]
3060     fn copy_custom_used_after() {
3061         check_assist(
3062             extract_function,
3063             r#"
3064 //- minicore: copy, derive
3065 #[derive(Clone, Copy)]
3066 struct Counter(i32);
3067 fn foo() {
3068     let c = Counter(0);
3069     $0let n = c.0;$0
3070     let m = c.0;
3071 }
3072 "#,
3073             r#"
3074 #[derive(Clone, Copy)]
3075 struct Counter(i32);
3076 fn foo() {
3077     let c = Counter(0);
3078     fun_name(c);
3079     let m = c.0;
3080 }
3081
3082 fn $0fun_name(c: Counter) {
3083     let n = c.0;
3084 }
3085 "#,
3086         );
3087     }
3088
3089     #[test]
3090     fn indented_stmts() {
3091         check_assist(
3092             extract_function,
3093             r#"
3094 fn foo() {
3095     if true {
3096         loop {
3097             $0let n = 1;
3098             let m = 2;$0
3099         }
3100     }
3101 }
3102 "#,
3103             r#"
3104 fn foo() {
3105     if true {
3106         loop {
3107             fun_name();
3108         }
3109     }
3110 }
3111
3112 fn $0fun_name() {
3113     let n = 1;
3114     let m = 2;
3115 }
3116 "#,
3117         );
3118     }
3119
3120     #[test]
3121     fn indented_stmts_inside_mod() {
3122         check_assist(
3123             extract_function,
3124             r#"
3125 mod bar {
3126     fn foo() {
3127         if true {
3128             loop {
3129                 $0let n = 1;
3130                 let m = 2;$0
3131             }
3132         }
3133     }
3134 }
3135 "#,
3136             r#"
3137 mod bar {
3138     fn foo() {
3139         if true {
3140             loop {
3141                 fun_name();
3142             }
3143         }
3144     }
3145
3146     fn $0fun_name() {
3147         let n = 1;
3148         let m = 2;
3149     }
3150 }
3151 "#,
3152         );
3153     }
3154
3155     #[test]
3156     fn break_loop() {
3157         check_assist(
3158             extract_function,
3159             r#"
3160 //- minicore: option
3161 fn foo() {
3162     loop {
3163         let n = 1;
3164         $0let m = n + 1;
3165         break;
3166         let k = 2;$0
3167         let h = 1 + k;
3168     }
3169 }
3170 "#,
3171             r#"
3172 fn foo() {
3173     loop {
3174         let n = 1;
3175         let k = match fun_name(n) {
3176             Some(value) => value,
3177             None => break,
3178         };
3179         let h = 1 + k;
3180     }
3181 }
3182
3183 fn $0fun_name(n: i32) -> Option<i32> {
3184     let m = n + 1;
3185     return None;
3186     let k = 2;
3187     Some(k)
3188 }
3189 "#,
3190         );
3191     }
3192
3193     #[test]
3194     fn return_to_parent() {
3195         check_assist(
3196             extract_function,
3197             r#"
3198 //- minicore: copy, result
3199 fn foo() -> i64 {
3200     let n = 1;
3201     $0let m = n + 1;
3202     return 1;
3203     let k = 2;$0
3204     (n + k) as i64
3205 }
3206 "#,
3207             r#"
3208 fn foo() -> i64 {
3209     let n = 1;
3210     let k = match fun_name(n) {
3211         Ok(value) => value,
3212         Err(value) => return value,
3213     };
3214     (n + k) as i64
3215 }
3216
3217 fn $0fun_name(n: i32) -> Result<i32, i64> {
3218     let m = n + 1;
3219     return Err(1);
3220     let k = 2;
3221     Ok(k)
3222 }
3223 "#,
3224         );
3225     }
3226
3227     #[test]
3228     fn break_and_continue() {
3229         cov_mark::check!(external_control_flow_break_and_continue);
3230         check_assist_not_applicable(
3231             extract_function,
3232             r#"
3233 fn foo() {
3234     loop {
3235         let n = 1;
3236         $0let m = n + 1;
3237         break;
3238         let k = 2;
3239         continue;
3240         let k = k + 1;$0
3241         let r = n + k;
3242     }
3243 }
3244 "#,
3245         );
3246     }
3247
3248     #[test]
3249     fn return_and_break() {
3250         cov_mark::check!(external_control_flow_return_and_bc);
3251         check_assist_not_applicable(
3252             extract_function,
3253             r#"
3254 fn foo() {
3255     loop {
3256         let n = 1;
3257         $0let m = n + 1;
3258         break;
3259         let k = 2;
3260         return;
3261         let k = k + 1;$0
3262         let r = n + k;
3263     }
3264 }
3265 "#,
3266         );
3267     }
3268
3269     #[test]
3270     fn break_loop_with_if() {
3271         check_assist(
3272             extract_function,
3273             r#"
3274 fn foo() {
3275     loop {
3276         let mut n = 1;
3277         $0let m = n + 1;
3278         break;
3279         n += m;$0
3280         let h = 1 + n;
3281     }
3282 }
3283 "#,
3284             r#"
3285 fn foo() {
3286     loop {
3287         let mut n = 1;
3288         if fun_name(&mut n) {
3289             break;
3290         }
3291         let h = 1 + n;
3292     }
3293 }
3294
3295 fn $0fun_name(n: &mut i32) -> bool {
3296     let m = *n + 1;
3297     return true;
3298     *n += m;
3299     false
3300 }
3301 "#,
3302         );
3303     }
3304
3305     #[test]
3306     fn break_loop_nested() {
3307         check_assist(
3308             extract_function,
3309             r#"
3310 fn foo() {
3311     loop {
3312         let mut n = 1;
3313         $0let m = n + 1;
3314         if m == 42 {
3315             break;
3316         }$0
3317         let h = 1;
3318     }
3319 }
3320 "#,
3321             r#"
3322 fn foo() {
3323     loop {
3324         let mut n = 1;
3325         if fun_name(n) {
3326             break;
3327         }
3328         let h = 1;
3329     }
3330 }
3331
3332 fn $0fun_name(n: i32) -> bool {
3333     let m = n + 1;
3334     if m == 42 {
3335         return true;
3336     }
3337     false
3338 }
3339 "#,
3340         );
3341     }
3342
3343     #[test]
3344     fn return_from_nested_loop() {
3345         check_assist(
3346             extract_function,
3347             r#"
3348 fn foo() {
3349     loop {
3350         let n = 1;$0
3351         let k = 1;
3352         loop {
3353             return;
3354         }
3355         let m = k + 1;$0
3356         let h = 1 + m;
3357     }
3358 }
3359 "#,
3360             r#"
3361 fn foo() {
3362     loop {
3363         let n = 1;
3364         let m = match fun_name() {
3365             Some(value) => value,
3366             None => return,
3367         };
3368         let h = 1 + m;
3369     }
3370 }
3371
3372 fn $0fun_name() -> Option<i32> {
3373     let k = 1;
3374     loop {
3375         return None;
3376     }
3377     let m = k + 1;
3378     Some(m)
3379 }
3380 "#,
3381         );
3382     }
3383
3384     #[test]
3385     fn break_from_nested_loop() {
3386         check_assist(
3387             extract_function,
3388             r#"
3389 fn foo() {
3390     loop {
3391         let n = 1;
3392         $0let k = 1;
3393         loop {
3394             break;
3395         }
3396         let m = k + 1;$0
3397         let h = 1 + m;
3398     }
3399 }
3400 "#,
3401             r#"
3402 fn foo() {
3403     loop {
3404         let n = 1;
3405         let m = fun_name();
3406         let h = 1 + m;
3407     }
3408 }
3409
3410 fn $0fun_name() -> i32 {
3411     let k = 1;
3412     loop {
3413         break;
3414     }
3415     let m = k + 1;
3416     m
3417 }
3418 "#,
3419         );
3420     }
3421
3422     #[test]
3423     fn break_from_nested_and_outer_loops() {
3424         check_assist(
3425             extract_function,
3426             r#"
3427 fn foo() {
3428     loop {
3429         let n = 1;
3430         $0let k = 1;
3431         loop {
3432             break;
3433         }
3434         if k == 42 {
3435             break;
3436         }
3437         let m = k + 1;$0
3438         let h = 1 + m;
3439     }
3440 }
3441 "#,
3442             r#"
3443 fn foo() {
3444     loop {
3445         let n = 1;
3446         let m = match fun_name() {
3447             Some(value) => value,
3448             None => break,
3449         };
3450         let h = 1 + m;
3451     }
3452 }
3453
3454 fn $0fun_name() -> Option<i32> {
3455     let k = 1;
3456     loop {
3457         break;
3458     }
3459     if k == 42 {
3460         return None;
3461     }
3462     let m = k + 1;
3463     Some(m)
3464 }
3465 "#,
3466         );
3467     }
3468
3469     #[test]
3470     fn return_from_nested_fn() {
3471         check_assist(
3472             extract_function,
3473             r#"
3474 fn foo() {
3475     loop {
3476         let n = 1;
3477         $0let k = 1;
3478         fn test() {
3479             return;
3480         }
3481         let m = k + 1;$0
3482         let h = 1 + m;
3483     }
3484 }
3485 "#,
3486             r#"
3487 fn foo() {
3488     loop {
3489         let n = 1;
3490         let m = fun_name();
3491         let h = 1 + m;
3492     }
3493 }
3494
3495 fn $0fun_name() -> i32 {
3496     let k = 1;
3497     fn test() {
3498         return;
3499     }
3500     let m = k + 1;
3501     m
3502 }
3503 "#,
3504         );
3505     }
3506
3507     #[test]
3508     fn break_with_value() {
3509         check_assist(
3510             extract_function,
3511             r#"
3512 fn foo() -> i32 {
3513     loop {
3514         let n = 1;
3515         $0let k = 1;
3516         if k == 42 {
3517             break 3;
3518         }
3519         let m = k + 1;$0
3520         let h = 1;
3521     }
3522 }
3523 "#,
3524             r#"
3525 fn foo() -> i32 {
3526     loop {
3527         let n = 1;
3528         if let Some(value) = fun_name() {
3529             break value;
3530         }
3531         let h = 1;
3532     }
3533 }
3534
3535 fn $0fun_name() -> Option<i32> {
3536     let k = 1;
3537     if k == 42 {
3538         return Some(3);
3539     }
3540     let m = k + 1;
3541     None
3542 }
3543 "#,
3544         );
3545     }
3546
3547     #[test]
3548     fn break_with_value_and_return() {
3549         check_assist(
3550             extract_function,
3551             r#"
3552 fn foo() -> i64 {
3553     loop {
3554         let n = 1;$0
3555         let k = 1;
3556         if k == 42 {
3557             break 3;
3558         }
3559         let m = k + 1;$0
3560         let h = 1 + m;
3561     }
3562 }
3563 "#,
3564             r#"
3565 fn foo() -> i64 {
3566     loop {
3567         let n = 1;
3568         let m = match fun_name() {
3569             Ok(value) => value,
3570             Err(value) => break value,
3571         };
3572         let h = 1 + m;
3573     }
3574 }
3575
3576 fn $0fun_name() -> Result<i32, i64> {
3577     let k = 1;
3578     if k == 42 {
3579         return Err(3);
3580     }
3581     let m = k + 1;
3582     Ok(m)
3583 }
3584 "#,
3585         );
3586     }
3587
3588     #[test]
3589     fn try_option() {
3590         check_assist(
3591             extract_function,
3592             r#"
3593 //- minicore: option
3594 fn bar() -> Option<i32> { None }
3595 fn foo() -> Option<()> {
3596     let n = bar()?;
3597     $0let k = foo()?;
3598     let m = k + 1;$0
3599     let h = 1 + m;
3600     Some(())
3601 }
3602 "#,
3603             r#"
3604 fn bar() -> Option<i32> { None }
3605 fn foo() -> Option<()> {
3606     let n = bar()?;
3607     let m = fun_name()?;
3608     let h = 1 + m;
3609     Some(())
3610 }
3611
3612 fn $0fun_name() -> Option<i32> {
3613     let k = foo()?;
3614     let m = k + 1;
3615     Some(m)
3616 }
3617 "#,
3618         );
3619     }
3620
3621     #[test]
3622     fn try_option_unit() {
3623         check_assist(
3624             extract_function,
3625             r#"
3626 //- minicore: option
3627 fn foo() -> Option<()> {
3628     let n = 1;
3629     $0let k = foo()?;
3630     let m = k + 1;$0
3631     let h = 1 + n;
3632     Some(())
3633 }
3634 "#,
3635             r#"
3636 fn foo() -> Option<()> {
3637     let n = 1;
3638     fun_name()?;
3639     let h = 1 + n;
3640     Some(())
3641 }
3642
3643 fn $0fun_name() -> Option<()> {
3644     let k = foo()?;
3645     let m = k + 1;
3646     Some(())
3647 }
3648 "#,
3649         );
3650     }
3651
3652     #[test]
3653     fn try_result() {
3654         check_assist(
3655             extract_function,
3656             r#"
3657 //- minicore: result
3658 fn foo() -> Result<(), i64> {
3659     let n = 1;
3660     $0let k = foo()?;
3661     let m = k + 1;$0
3662     let h = 1 + m;
3663     Ok(())
3664 }
3665 "#,
3666             r#"
3667 fn foo() -> Result<(), i64> {
3668     let n = 1;
3669     let m = fun_name()?;
3670     let h = 1 + m;
3671     Ok(())
3672 }
3673
3674 fn $0fun_name() -> Result<i32, i64> {
3675     let k = foo()?;
3676     let m = k + 1;
3677     Ok(m)
3678 }
3679 "#,
3680         );
3681     }
3682
3683     #[test]
3684     fn try_option_with_return() {
3685         check_assist(
3686             extract_function,
3687             r#"
3688 //- minicore: option
3689 fn foo() -> Option<()> {
3690     let n = 1;
3691     $0let k = foo()?;
3692     if k == 42 {
3693         return None;
3694     }
3695     let m = k + 1;$0
3696     let h = 1 + m;
3697     Some(())
3698 }
3699 "#,
3700             r#"
3701 fn foo() -> Option<()> {
3702     let n = 1;
3703     let m = fun_name()?;
3704     let h = 1 + m;
3705     Some(())
3706 }
3707
3708 fn $0fun_name() -> Option<i32> {
3709     let k = foo()?;
3710     if k == 42 {
3711         return None;
3712     }
3713     let m = k + 1;
3714     Some(m)
3715 }
3716 "#,
3717         );
3718     }
3719
3720     #[test]
3721     fn try_result_with_return() {
3722         check_assist(
3723             extract_function,
3724             r#"
3725 //- minicore: result
3726 fn foo() -> Result<(), i64> {
3727     let n = 1;
3728     $0let k = foo()?;
3729     if k == 42 {
3730         return Err(1);
3731     }
3732     let m = k + 1;$0
3733     let h = 1 + m;
3734     Ok(())
3735 }
3736 "#,
3737             r#"
3738 fn foo() -> Result<(), i64> {
3739     let n = 1;
3740     let m = fun_name()?;
3741     let h = 1 + m;
3742     Ok(())
3743 }
3744
3745 fn $0fun_name() -> Result<i32, i64> {
3746     let k = foo()?;
3747     if k == 42 {
3748         return Err(1);
3749     }
3750     let m = k + 1;
3751     Ok(m)
3752 }
3753 "#,
3754         );
3755     }
3756
3757     #[test]
3758     fn try_and_break() {
3759         cov_mark::check!(external_control_flow_try_and_bc);
3760         check_assist_not_applicable(
3761             extract_function,
3762             r#"
3763 //- minicore: option
3764 fn foo() -> Option<()> {
3765     loop {
3766         let n = Some(1);
3767         $0let m = n? + 1;
3768         break;
3769         let k = 2;
3770         let k = k + 1;$0
3771         let r = n + k;
3772     }
3773     Some(())
3774 }
3775 "#,
3776         );
3777     }
3778
3779     #[test]
3780     fn try_and_return_ok() {
3781         check_assist(
3782             extract_function,
3783             r#"
3784 //- minicore: result
3785 fn foo() -> Result<(), i64> {
3786     let n = 1;
3787     $0let k = foo()?;
3788     if k == 42 {
3789         return Ok(1);
3790     }
3791     let m = k + 1;$0
3792     let h = 1 + m;
3793     Ok(())
3794 }
3795 "#,
3796             r#"
3797 fn foo() -> Result<(), i64> {
3798     let n = 1;
3799     let m = fun_name()?;
3800     let h = 1 + m;
3801     Ok(())
3802 }
3803
3804 fn $0fun_name() -> Result<i32, i64> {
3805     let k = foo()?;
3806     if k == 42 {
3807         return Ok(1);
3808     }
3809     let m = k + 1;
3810     Ok(m)
3811 }
3812 "#,
3813         );
3814     }
3815
3816     #[test]
3817     fn param_usage_in_macro() {
3818         check_assist(
3819             extract_function,
3820             r#"
3821 macro_rules! m {
3822     ($val:expr) => { $val };
3823 }
3824
3825 fn foo() {
3826     let n = 1;
3827     $0let k = n * m!(n);$0
3828     let m = k + 1;
3829 }
3830 "#,
3831             r#"
3832 macro_rules! m {
3833     ($val:expr) => { $val };
3834 }
3835
3836 fn foo() {
3837     let n = 1;
3838     let k = fun_name(n);
3839     let m = k + 1;
3840 }
3841
3842 fn $0fun_name(n: i32) -> i32 {
3843     let k = n * m!(n);
3844     k
3845 }
3846 "#,
3847         );
3848     }
3849
3850     #[test]
3851     fn extract_with_await() {
3852         check_assist(
3853             extract_function,
3854             r#"
3855 fn main() {
3856     $0some_function().await;$0
3857 }
3858
3859 async fn some_function() {
3860
3861 }
3862 "#,
3863             r#"
3864 fn main() {
3865     fun_name().await;
3866 }
3867
3868 async fn $0fun_name() {
3869     some_function().await;
3870 }
3871
3872 async fn some_function() {
3873
3874 }
3875 "#,
3876         );
3877     }
3878
3879     #[test]
3880     fn extract_with_await_and_result_not_producing_match_expr() {
3881         check_assist(
3882             extract_function,
3883             r#"
3884 async fn foo() -> Result<(), ()> {
3885     $0async {}.await;
3886     Err(())?$0
3887 }
3888 "#,
3889             r#"
3890 async fn foo() -> Result<(), ()> {
3891     fun_name().await?
3892 }
3893
3894 async fn $0fun_name() -> _ {
3895     async {}.await;
3896     Err(())?
3897 }
3898 "#,
3899         );
3900     }
3901
3902     #[test]
3903     fn extract_with_await_and_result_producing_match_expr() {
3904         check_assist(
3905             extract_function,
3906             r#"
3907 async fn foo() -> i32 {
3908     loop {
3909         let n = 1;$0
3910         let k = async { 1 }.await;
3911         if k == 42 {
3912             break 3;
3913         }
3914         let m = k + 1;$0
3915         let h = 1 + m;
3916     }
3917 }
3918 "#,
3919             r#"
3920 async fn foo() -> i32 {
3921     loop {
3922         let n = 1;
3923         let m = match fun_name().await {
3924             Ok(value) => value,
3925             Err(value) => break value,
3926         };
3927         let h = 1 + m;
3928     }
3929 }
3930
3931 async fn $0fun_name() -> Result<i32, i32> {
3932     let k = async { 1 }.await;
3933     if k == 42 {
3934         return Err(3);
3935     }
3936     let m = k + 1;
3937     Ok(m)
3938 }
3939 "#,
3940         );
3941     }
3942
3943     #[test]
3944     fn extract_with_await_in_args() {
3945         check_assist(
3946             extract_function,
3947             r#"
3948 fn main() {
3949     $0function_call("a", some_function().await);$0
3950 }
3951
3952 async fn some_function() {
3953
3954 }
3955 "#,
3956             r#"
3957 fn main() {
3958     fun_name().await;
3959 }
3960
3961 async fn $0fun_name() {
3962     function_call("a", some_function().await);
3963 }
3964
3965 async fn some_function() {
3966
3967 }
3968 "#,
3969         );
3970     }
3971
3972     #[test]
3973     fn extract_does_not_extract_standalone_blocks() {
3974         check_assist_not_applicable(
3975             extract_function,
3976             r#"
3977 fn main() $0{}$0
3978 "#,
3979         );
3980     }
3981
3982     #[test]
3983     fn extract_adds_comma_for_match_arm() {
3984         check_assist(
3985             extract_function,
3986             r#"
3987 fn main() {
3988     match 6 {
3989         100 => $0{ 100 }$0
3990         _ => 0,
3991     }
3992 }
3993 "#,
3994             r#"
3995 fn main() {
3996     match 6 {
3997         100 => fun_name(),
3998         _ => 0,
3999     }
4000 }
4001
4002 fn $0fun_name() -> i32 {
4003     100
4004 }
4005 "#,
4006         );
4007         check_assist(
4008             extract_function,
4009             r#"
4010 fn main() {
4011     match 6 {
4012         100 => $0{ 100 }$0,
4013         _ => 0,
4014     }
4015 }
4016 "#,
4017             r#"
4018 fn main() {
4019     match 6 {
4020         100 => fun_name(),
4021         _ => 0,
4022     }
4023 }
4024
4025 fn $0fun_name() -> i32 {
4026     100
4027 }
4028 "#,
4029         );
4030     }
4031
4032     #[test]
4033     fn extract_does_not_tear_comments_apart() {
4034         check_assist(
4035             extract_function,
4036             r#"
4037 fn foo() {
4038     /*$0*/
4039     foo();
4040     foo();
4041     /*$0*/
4042 }
4043 "#,
4044             r#"
4045 fn foo() {
4046     /**/
4047     fun_name();
4048     /**/
4049 }
4050
4051 fn $0fun_name() {
4052     foo();
4053     foo();
4054 }
4055 "#,
4056         );
4057     }
4058
4059     #[test]
4060     fn extract_does_not_wrap_res_in_res() {
4061         check_assist(
4062             extract_function,
4063             r#"
4064 //- minicore: result
4065 fn foo() -> Result<(), i64> {
4066     $0Result::<i32, i64>::Ok(0)?;
4067     Ok(())$0
4068 }
4069 "#,
4070             r#"
4071 fn foo() -> Result<(), i64> {
4072     fun_name()?
4073 }
4074
4075 fn $0fun_name() -> Result<(), i64> {
4076     Result::<i32, i64>::Ok(0)?;
4077     Ok(())
4078 }
4079 "#,
4080         );
4081     }
4082
4083     #[test]
4084     fn extract_knows_const() {
4085         check_assist(
4086             extract_function,
4087             r#"
4088 const fn foo() {
4089     $0()$0
4090 }
4091 "#,
4092             r#"
4093 const fn foo() {
4094     fun_name();
4095 }
4096
4097 const fn $0fun_name() {
4098     ()
4099 }
4100 "#,
4101         );
4102         check_assist(
4103             extract_function,
4104             r#"
4105 const FOO: () = {
4106     $0()$0
4107 };
4108 "#,
4109             r#"
4110 const FOO: () = {
4111     fun_name();
4112 };
4113
4114 const fn $0fun_name() {
4115     ()
4116 }
4117 "#,
4118         );
4119     }
4120
4121     #[test]
4122     fn extract_does_not_move_outer_loop_vars() {
4123         check_assist(
4124             extract_function,
4125             r#"
4126 fn foo() {
4127     let mut x = 5;
4128     for _ in 0..10 {
4129         $0x += 1;$0
4130     }
4131 }
4132 "#,
4133             r#"
4134 fn foo() {
4135     let mut x = 5;
4136     for _ in 0..10 {
4137         fun_name(&mut x);
4138     }
4139 }
4140
4141 fn $0fun_name(x: &mut i32) {
4142     *x += 1;
4143 }
4144 "#,
4145         );
4146         check_assist(
4147             extract_function,
4148             r#"
4149 fn foo() {
4150     for _ in 0..10 {
4151         let mut x = 5;
4152         $0x += 1;$0
4153     }
4154 }
4155 "#,
4156             r#"
4157 fn foo() {
4158     for _ in 0..10 {
4159         let mut x = 5;
4160         fun_name(x);
4161     }
4162 }
4163
4164 fn $0fun_name(mut x: i32) {
4165     x += 1;
4166 }
4167 "#,
4168         );
4169         check_assist(
4170             extract_function,
4171             r#"
4172 fn foo() {
4173     loop {
4174         let mut x = 5;
4175         for _ in 0..10 {
4176             $0x += 1;$0
4177         }
4178     }
4179 }
4180 "#,
4181             r#"
4182 fn foo() {
4183     loop {
4184         let mut x = 5;
4185         for _ in 0..10 {
4186             fun_name(&mut x);
4187         }
4188     }
4189 }
4190
4191 fn $0fun_name(x: &mut i32) {
4192     *x += 1;
4193 }
4194 "#,
4195         );
4196     }
4197
4198     // regression test for #9822
4199     #[test]
4200     fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4201         check_assist(
4202             extract_function,
4203             r#"
4204 struct Foo;
4205 impl Foo {
4206     fn foo(&mut self) {}
4207 }
4208 fn foo() {
4209     let mut x = Foo;
4210     while false {
4211         let y = &mut x;
4212         $0y.foo();$0
4213     }
4214     let z = x;
4215 }
4216 "#,
4217             r#"
4218 struct Foo;
4219 impl Foo {
4220     fn foo(&mut self) {}
4221 }
4222 fn foo() {
4223     let mut x = Foo;
4224     while false {
4225         let y = &mut x;
4226         fun_name(y);
4227     }
4228     let z = x;
4229 }
4230
4231 fn $0fun_name(y: &mut Foo) {
4232     y.foo();
4233 }
4234 "#,
4235         );
4236     }
4237
4238     #[test]
4239     fn extract_with_macro_arg() {
4240         check_assist(
4241             extract_function,
4242             r#"
4243 macro_rules! m {
4244     ($val:expr) => { $val };
4245 }
4246 fn main() {
4247     let bar = "bar";
4248     $0m!(bar);$0
4249 }
4250 "#,
4251             r#"
4252 macro_rules! m {
4253     ($val:expr) => { $val };
4254 }
4255 fn main() {
4256     let bar = "bar";
4257     fun_name(bar);
4258 }
4259
4260 fn $0fun_name(bar: &str) {
4261     m!(bar);
4262 }
4263 "#,
4264         );
4265     }
4266
4267     #[test]
4268     fn unresolveable_types_default_to_placeholder() {
4269         check_assist(
4270             extract_function,
4271             r#"
4272 fn foo() {
4273     let a = __unresolved;
4274     let _ = $0{a}$0;
4275 }
4276 "#,
4277             r#"
4278 fn foo() {
4279     let a = __unresolved;
4280     let _ = fun_name(a);
4281 }
4282
4283 fn $0fun_name(a: _) -> _ {
4284     a
4285 }
4286 "#,
4287         );
4288     }
4289 }