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