]> git.lizzy.rs Git - rust.git/blob - crates/ide_assists/src/handlers/extract_function.rs
Merge #11481
[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::expr_let(
1223                     make::tuple_struct_pat(
1224                         controlflow_break_path,
1225                         iter::once(make::wildcard_pat().into()),
1226                     )
1227                     .into(),
1228                     call_expr,
1229                 );
1230                 make::expr_if(condition.into(), block, None)
1231             }
1232             FlowHandler::IfOption { action } => {
1233                 let path = make::ext::ident_path("Some");
1234                 let value_pat = make::ext::simple_ident_pat(make::name("value"));
1235                 let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1236                 let cond = make::expr_let(pattern.into(), call_expr);
1237                 let value = make::expr_path(make::ext::ident_path("value"));
1238                 let action_expr = action.make_result_handler(Some(value));
1239                 let action_stmt = make::expr_stmt(action_expr);
1240                 let then = make::block_expr(iter::once(action_stmt.into()), None);
1241                 make::expr_if(cond.into(), then, None)
1242             }
1243             FlowHandler::MatchOption { none } => {
1244                 let some_name = "value";
1245
1246                 let some_arm = {
1247                     let path = make::ext::ident_path("Some");
1248                     let value_pat = make::ext::simple_ident_pat(make::name(some_name));
1249                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1250                     let value = make::expr_path(make::ext::ident_path(some_name));
1251                     make::match_arm(iter::once(pat.into()), None, value)
1252                 };
1253                 let none_arm = {
1254                     let path = make::ext::ident_path("None");
1255                     let pat = make::path_pat(path);
1256                     make::match_arm(iter::once(pat), None, none.make_result_handler(None))
1257                 };
1258                 let arms = make::match_arm_list(vec![some_arm, none_arm]);
1259                 make::expr_match(call_expr, arms)
1260             }
1261             FlowHandler::MatchResult { err } => {
1262                 let ok_name = "value";
1263                 let err_name = "value";
1264
1265                 let ok_arm = {
1266                     let path = make::ext::ident_path("Ok");
1267                     let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
1268                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1269                     let value = make::expr_path(make::ext::ident_path(ok_name));
1270                     make::match_arm(iter::once(pat.into()), None, value)
1271                 };
1272                 let err_arm = {
1273                     let path = make::ext::ident_path("Err");
1274                     let value_pat = make::ext::simple_ident_pat(make::name(err_name));
1275                     let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1276                     let value = make::expr_path(make::ext::ident_path(err_name));
1277                     make::match_arm(
1278                         iter::once(pat.into()),
1279                         None,
1280                         err.make_result_handler(Some(value)),
1281                     )
1282                 };
1283                 let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1284                 make::expr_match(call_expr, arms)
1285             }
1286         }
1287     }
1288 }
1289
1290 fn path_expr_from_local(ctx: &AssistContext, var: Local) -> ast::Expr {
1291     let name = var.name(ctx.db()).unwrap().to_string();
1292     make::expr_path(make::ext::ident_path(&name))
1293 }
1294
1295 fn format_function(
1296     ctx: &AssistContext,
1297     module: hir::Module,
1298     fun: &Function,
1299     old_indent: IndentLevel,
1300     new_indent: IndentLevel,
1301 ) -> String {
1302     let mut fn_def = String::new();
1303     let params = fun.make_param_list(ctx, module);
1304     let ret_ty = fun.make_ret_ty(ctx, module);
1305     let body = make_body(ctx, old_indent, new_indent, fun);
1306     let const_kw = if fun.mods.is_const { "const " } else { "" };
1307     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
1308     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
1309     match ctx.config.snippet_cap {
1310         Some(_) => format_to!(
1311             fn_def,
1312             "\n\n{}{}{}{}fn $0{}{}",
1313             new_indent,
1314             const_kw,
1315             async_kw,
1316             unsafe_kw,
1317             fun.name,
1318             params
1319         ),
1320         None => format_to!(
1321             fn_def,
1322             "\n\n{}{}{}{}fn {}{}",
1323             new_indent,
1324             const_kw,
1325             async_kw,
1326             unsafe_kw,
1327             fun.name,
1328             params
1329         ),
1330     }
1331     if let Some(ret_ty) = ret_ty {
1332         format_to!(fn_def, " {}", ret_ty);
1333     }
1334     format_to!(fn_def, " {}", body);
1335
1336     fn_def
1337 }
1338
1339 impl Function {
1340     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
1341         let self_param = self.self_param.clone();
1342         let params = self.params.iter().map(|param| param.to_param(ctx, module));
1343         make::param_list(self_param, params)
1344     }
1345
1346     fn make_ret_ty(&self, ctx: &AssistContext, module: hir::Module) -> Option<ast::RetType> {
1347         let fun_ty = self.return_type(ctx);
1348         let handler = if self.mods.is_in_tail {
1349             FlowHandler::None
1350         } else {
1351             FlowHandler::from_ret_ty(self, &fun_ty)
1352         };
1353         let ret_ty = match &handler {
1354             FlowHandler::None => {
1355                 if matches!(fun_ty, FunType::Unit) {
1356                     return None;
1357                 }
1358                 fun_ty.make_ty(ctx, module)
1359             }
1360             FlowHandler::Try { kind: TryKind::Option } => {
1361                 make::ext::ty_option(fun_ty.make_ty(ctx, module))
1362             }
1363             FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1364                 let handler_ty = parent_ret_ty
1365                     .type_arguments()
1366                     .nth(1)
1367                     .map(|ty| make_ty(&ty, ctx, module))
1368                     .unwrap_or_else(make::ty_placeholder);
1369                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1370             }
1371             FlowHandler::If { .. } => make::ty("ControlFlow<()>"),
1372             FlowHandler::IfOption { action } => {
1373                 let handler_ty = action
1374                     .expr_ty(ctx)
1375                     .map(|ty| make_ty(&ty, ctx, module))
1376                     .unwrap_or_else(make::ty_placeholder);
1377                 make::ext::ty_option(handler_ty)
1378             }
1379             FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1380             FlowHandler::MatchResult { err } => {
1381                 let handler_ty = err
1382                     .expr_ty(ctx)
1383                     .map(|ty| make_ty(&ty, ctx, module))
1384                     .unwrap_or_else(make::ty_placeholder);
1385                 make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1386             }
1387         };
1388         Some(make::ret_type(ret_ty))
1389     }
1390 }
1391
1392 impl FunType {
1393     fn make_ty(&self, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1394         match self {
1395             FunType::Unit => make::ty_unit(),
1396             FunType::Single(ty) => make_ty(ty, ctx, module),
1397             FunType::Tuple(types) => match types.as_slice() {
1398                 [] => {
1399                     stdx::never!("tuple type with 0 elements");
1400                     make::ty_unit()
1401                 }
1402                 [ty] => {
1403                     stdx::never!("tuple type with 1 element");
1404                     make_ty(ty, ctx, module)
1405                 }
1406                 types => {
1407                     let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1408                     make::ty_tuple(types)
1409                 }
1410             },
1411         }
1412     }
1413 }
1414
1415 fn make_body(
1416     ctx: &AssistContext,
1417     old_indent: IndentLevel,
1418     new_indent: IndentLevel,
1419     fun: &Function,
1420 ) -> ast::BlockExpr {
1421     let ret_ty = fun.return_type(ctx);
1422     let handler = if fun.mods.is_in_tail {
1423         FlowHandler::None
1424     } else {
1425         FlowHandler::from_ret_ty(fun, &ret_ty)
1426     };
1427
1428     let block = match &fun.body {
1429         FunctionBody::Expr(expr) => {
1430             let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1431             let expr = ast::Expr::cast(expr).unwrap();
1432             match expr {
1433                 ast::Expr::BlockExpr(block) => {
1434                     // If the extracted expression is itself a block, there is no need to wrap it inside another block.
1435                     let block = block.dedent(old_indent);
1436                     // Recreate the block for formatting consistency with other extracted functions.
1437                     make::block_expr(block.statements(), block.tail_expr())
1438                 }
1439                 _ => {
1440                     let expr = expr.dedent(old_indent).indent(IndentLevel(1));
1441
1442                     make::block_expr(Vec::new(), Some(expr))
1443                 }
1444             }
1445         }
1446         FunctionBody::Span { parent, text_range } => {
1447             let mut elements: Vec<_> = parent
1448                 .syntax()
1449                 .children_with_tokens()
1450                 .filter(|it| text_range.contains_range(it.text_range()))
1451                 .map(|it| match &it {
1452                     syntax::NodeOrToken::Node(n) => syntax::NodeOrToken::Node(
1453                         rewrite_body_segment(ctx, &fun.params, &handler, &n),
1454                     ),
1455                     _ => it,
1456                 })
1457                 .collect();
1458
1459             let mut tail_expr = match &elements.last() {
1460                 Some(syntax::NodeOrToken::Node(node)) if ast::Expr::can_cast(node.kind()) => {
1461                     ast::Expr::cast(node.clone())
1462                 }
1463                 _ => None,
1464             };
1465
1466             match tail_expr {
1467                 Some(_) => {
1468                     elements.pop();
1469                 }
1470                 None => match fun.outliving_locals.as_slice() {
1471                     [] => {}
1472                     [var] => {
1473                         tail_expr = Some(path_expr_from_local(ctx, var.local));
1474                     }
1475                     vars => {
1476                         let exprs = vars.iter().map(|var| path_expr_from_local(ctx, var.local));
1477                         let expr = make::expr_tuple(exprs);
1478                         tail_expr = Some(expr);
1479                     }
1480                 },
1481             };
1482
1483             let body_indent = IndentLevel(1);
1484             let elements = elements
1485                 .into_iter()
1486                 .map(|node_or_token| match &node_or_token {
1487                     syntax::NodeOrToken::Node(node) => match ast::Stmt::cast(node.clone()) {
1488                         Some(stmt) => {
1489                             let indented = stmt.dedent(old_indent).indent(body_indent);
1490                             let ast_node = indented.syntax().clone_subtree();
1491                             syntax::NodeOrToken::Node(ast_node)
1492                         }
1493                         _ => node_or_token,
1494                     },
1495                     _ => node_or_token,
1496                 })
1497                 .collect::<Vec<SyntaxElement>>();
1498             let tail_expr = tail_expr.map(|expr| expr.dedent(old_indent).indent(body_indent));
1499
1500             make::hacky_block_expr_with_comments(elements, tail_expr)
1501         }
1502     };
1503
1504     let block = match &handler {
1505         FlowHandler::None => block,
1506         FlowHandler::Try { kind } => {
1507             let block = with_default_tail_expr(block, make::expr_unit());
1508             map_tail_expr(block, |tail_expr| {
1509                 let constructor = match kind {
1510                     TryKind::Option => "Some",
1511                     TryKind::Result { .. } => "Ok",
1512                 };
1513                 let func = make::expr_path(make::ext::ident_path(constructor));
1514                 let args = make::arg_list(iter::once(tail_expr));
1515                 make::expr_call(func, args)
1516             })
1517         }
1518         FlowHandler::If { .. } => {
1519             let controlflow_continue = make::expr_call(
1520                 make::expr_path(make::path_from_text("ControlFlow::Continue")),
1521                 make::arg_list(iter::once(make::expr_unit())),
1522             );
1523             with_tail_expr(block, controlflow_continue.into())
1524         }
1525         FlowHandler::IfOption { .. } => {
1526             let none = make::expr_path(make::ext::ident_path("None"));
1527             with_tail_expr(block, none)
1528         }
1529         FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1530             let some = make::expr_path(make::ext::ident_path("Some"));
1531             let args = make::arg_list(iter::once(tail_expr));
1532             make::expr_call(some, args)
1533         }),
1534         FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1535             let ok = make::expr_path(make::ext::ident_path("Ok"));
1536             let args = make::arg_list(iter::once(tail_expr));
1537             make::expr_call(ok, args)
1538         }),
1539     };
1540
1541     block.indent(new_indent)
1542 }
1543
1544 fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1545     let tail_expr = match block.tail_expr() {
1546         Some(tail_expr) => tail_expr,
1547         None => return block,
1548     };
1549     make::block_expr(block.statements(), Some(f(tail_expr)))
1550 }
1551
1552 fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1553     match block.tail_expr() {
1554         Some(_) => block,
1555         None => make::block_expr(block.statements(), Some(tail_expr)),
1556     }
1557 }
1558
1559 fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1560     let stmt_tail = block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1561     let stmts = block.statements().chain(stmt_tail);
1562     make::block_expr(stmts, Some(tail_expr))
1563 }
1564
1565 fn format_type(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> String {
1566     ty.display_source_code(ctx.db(), module.into()).ok().unwrap_or_else(|| "_".to_string())
1567 }
1568
1569 fn make_ty(ty: &hir::Type, ctx: &AssistContext, module: hir::Module) -> ast::Type {
1570     let ty_str = format_type(ty, ctx, module);
1571     make::ty(&ty_str)
1572 }
1573
1574 fn rewrite_body_segment(
1575     ctx: &AssistContext,
1576     params: &[Param],
1577     handler: &FlowHandler,
1578     syntax: &SyntaxNode,
1579 ) -> SyntaxNode {
1580     let syntax = fix_param_usages(ctx, params, syntax);
1581     update_external_control_flow(handler, &syntax);
1582     syntax
1583 }
1584
1585 /// change all usages to account for added `&`/`&mut` for some params
1586 fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode) -> SyntaxNode {
1587     let mut usages_for_param: Vec<(&Param, Vec<ast::Expr>)> = Vec::new();
1588
1589     let tm = TreeMutator::new(syntax);
1590
1591     for param in params {
1592         if !param.kind().is_ref() {
1593             continue;
1594         }
1595
1596         let usages = LocalUsages::find_local_usages(ctx, param.var);
1597         let usages = usages
1598             .iter()
1599             .filter(|reference| syntax.text_range().contains_range(reference.range))
1600             .filter_map(|reference| path_element_of_reference(syntax, reference))
1601             .map(|expr| tm.make_mut(&expr));
1602
1603         usages_for_param.push((param, usages.collect()));
1604     }
1605
1606     let res = tm.make_syntax_mut(syntax);
1607
1608     for (param, usages) in usages_for_param {
1609         for usage in usages {
1610             match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
1611                 Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
1612                     // do nothing
1613                 }
1614                 Some(ast::Expr::RefExpr(node))
1615                     if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
1616                 {
1617                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1618                 }
1619                 Some(ast::Expr::RefExpr(node))
1620                     if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
1621                 {
1622                     ted::replace(node.syntax(), node.expr().unwrap().syntax());
1623                 }
1624                 Some(_) | None => {
1625                     let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update();
1626                     ted::replace(usage.syntax(), p.syntax())
1627                 }
1628             }
1629         }
1630     }
1631
1632     res
1633 }
1634
1635 fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) {
1636     let mut nested_loop = None;
1637     let mut nested_scope = None;
1638     for event in syntax.preorder() {
1639         match event {
1640             WalkEvent::Enter(e) => match e.kind() {
1641                 SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
1642                     if nested_loop.is_none() {
1643                         nested_loop = Some(e.clone());
1644                     }
1645                 }
1646                 SyntaxKind::FN
1647                 | SyntaxKind::CONST
1648                 | SyntaxKind::STATIC
1649                 | SyntaxKind::IMPL
1650                 | SyntaxKind::MODULE => {
1651                     if nested_scope.is_none() {
1652                         nested_scope = Some(e.clone());
1653                     }
1654                 }
1655                 _ => {}
1656             },
1657             WalkEvent::Leave(e) => {
1658                 if nested_scope.is_none() {
1659                     if let Some(expr) = ast::Expr::cast(e.clone()) {
1660                         match expr {
1661                             ast::Expr::ReturnExpr(return_expr) if nested_scope.is_none() => {
1662                                 let expr = return_expr.expr();
1663                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1664                                     ted::replace(return_expr.syntax(), replacement.syntax())
1665                                 }
1666                             }
1667                             ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
1668                                 let expr = break_expr.expr();
1669                                 if let Some(replacement) = make_rewritten_flow(handler, expr) {
1670                                     ted::replace(break_expr.syntax(), replacement.syntax())
1671                                 }
1672                             }
1673                             ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
1674                                 if let Some(replacement) = make_rewritten_flow(handler, None) {
1675                                     ted::replace(continue_expr.syntax(), replacement.syntax())
1676                                 }
1677                             }
1678                             _ => {
1679                                 // do nothing
1680                             }
1681                         }
1682                     }
1683                 }
1684
1685                 if nested_loop.as_ref() == Some(&e) {
1686                     nested_loop = None;
1687                 }
1688                 if nested_scope.as_ref() == Some(&e) {
1689                     nested_scope = None;
1690                 }
1691             }
1692         };
1693     }
1694 }
1695
1696 fn make_rewritten_flow(handler: &FlowHandler, arg_expr: Option<ast::Expr>) -> Option<ast::Expr> {
1697     let value = match handler {
1698         FlowHandler::None | FlowHandler::Try { .. } => return None,
1699         FlowHandler::If { .. } => make::expr_call(
1700             make::expr_path(make::path_from_text("ControlFlow::Break")),
1701             make::arg_list(iter::once(make::expr_unit())),
1702         ),
1703         FlowHandler::IfOption { .. } => {
1704             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1705             let args = make::arg_list(iter::once(expr));
1706             make::expr_call(make::expr_path(make::ext::ident_path("Some")), args)
1707         }
1708         FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
1709         FlowHandler::MatchResult { .. } => {
1710             let expr = arg_expr.unwrap_or_else(|| make::expr_tuple(Vec::new()));
1711             let args = make::arg_list(iter::once(expr));
1712             make::expr_call(make::expr_path(make::ext::ident_path("Err")), args)
1713         }
1714     };
1715     Some(make::expr_return(Some(value)).clone_for_update())
1716 }
1717
1718 #[cfg(test)]
1719 mod tests {
1720     use crate::tests::{check_assist, check_assist_not_applicable};
1721
1722     use super::*;
1723
1724     #[test]
1725     fn no_args_from_binary_expr() {
1726         check_assist(
1727             extract_function,
1728             r#"
1729 fn foo() {
1730     foo($01 + 1$0);
1731 }
1732 "#,
1733             r#"
1734 fn foo() {
1735     foo(fun_name());
1736 }
1737
1738 fn $0fun_name() -> i32 {
1739     1 + 1
1740 }
1741 "#,
1742         );
1743     }
1744
1745     #[test]
1746     fn no_args_from_binary_expr_in_module() {
1747         check_assist(
1748             extract_function,
1749             r#"
1750 mod bar {
1751     fn foo() {
1752         foo($01 + 1$0);
1753     }
1754 }
1755 "#,
1756             r#"
1757 mod bar {
1758     fn foo() {
1759         foo(fun_name());
1760     }
1761
1762     fn $0fun_name() -> i32 {
1763         1 + 1
1764     }
1765 }
1766 "#,
1767         );
1768     }
1769
1770     #[test]
1771     fn no_args_from_binary_expr_indented() {
1772         check_assist(
1773             extract_function,
1774             r#"
1775 fn foo() {
1776     $0{ 1 + 1 }$0;
1777 }
1778 "#,
1779             r#"
1780 fn foo() {
1781     fun_name();
1782 }
1783
1784 fn $0fun_name() -> i32 {
1785     1 + 1
1786 }
1787 "#,
1788         );
1789     }
1790
1791     #[test]
1792     fn no_args_from_stmt_with_last_expr() {
1793         check_assist(
1794             extract_function,
1795             r#"
1796 fn foo() -> i32 {
1797     let k = 1;
1798     $0let m = 1;
1799     m + 1$0
1800 }
1801 "#,
1802             r#"
1803 fn foo() -> i32 {
1804     let k = 1;
1805     fun_name()
1806 }
1807
1808 fn $0fun_name() -> i32 {
1809     let m = 1;
1810     m + 1
1811 }
1812 "#,
1813         );
1814     }
1815
1816     #[test]
1817     fn no_args_from_stmt_unit() {
1818         check_assist(
1819             extract_function,
1820             r#"
1821 fn foo() {
1822     let k = 3;
1823     $0let m = 1;
1824     let n = m + 1;$0
1825     let g = 5;
1826 }
1827 "#,
1828             r#"
1829 fn foo() {
1830     let k = 3;
1831     fun_name();
1832     let g = 5;
1833 }
1834
1835 fn $0fun_name() {
1836     let m = 1;
1837     let n = m + 1;
1838 }
1839 "#,
1840         );
1841     }
1842
1843     #[test]
1844     fn no_args_if() {
1845         check_assist(
1846             extract_function,
1847             r#"
1848 fn foo() {
1849     $0if true { }$0
1850 }
1851 "#,
1852             r#"
1853 fn foo() {
1854     fun_name();
1855 }
1856
1857 fn $0fun_name() {
1858     if true { }
1859 }
1860 "#,
1861         );
1862     }
1863
1864     #[test]
1865     fn no_args_if_else() {
1866         check_assist(
1867             extract_function,
1868             r#"
1869 fn foo() -> i32 {
1870     $0if true { 1 } else { 2 }$0
1871 }
1872 "#,
1873             r#"
1874 fn foo() -> i32 {
1875     fun_name()
1876 }
1877
1878 fn $0fun_name() -> i32 {
1879     if true { 1 } else { 2 }
1880 }
1881 "#,
1882         );
1883     }
1884
1885     #[test]
1886     fn no_args_if_let_else() {
1887         check_assist(
1888             extract_function,
1889             r#"
1890 fn foo() -> i32 {
1891     $0if let true = false { 1 } else { 2 }$0
1892 }
1893 "#,
1894             r#"
1895 fn foo() -> i32 {
1896     fun_name()
1897 }
1898
1899 fn $0fun_name() -> i32 {
1900     if let true = false { 1 } else { 2 }
1901 }
1902 "#,
1903         );
1904     }
1905
1906     #[test]
1907     fn no_args_match() {
1908         check_assist(
1909             extract_function,
1910             r#"
1911 fn foo() -> i32 {
1912     $0match true {
1913         true => 1,
1914         false => 2,
1915     }$0
1916 }
1917 "#,
1918             r#"
1919 fn foo() -> i32 {
1920     fun_name()
1921 }
1922
1923 fn $0fun_name() -> i32 {
1924     match true {
1925         true => 1,
1926         false => 2,
1927     }
1928 }
1929 "#,
1930         );
1931     }
1932
1933     #[test]
1934     fn no_args_while() {
1935         check_assist(
1936             extract_function,
1937             r#"
1938 fn foo() {
1939     $0while true { }$0
1940 }
1941 "#,
1942             r#"
1943 fn foo() {
1944     fun_name();
1945 }
1946
1947 fn $0fun_name() {
1948     while true { }
1949 }
1950 "#,
1951         );
1952     }
1953
1954     #[test]
1955     fn no_args_for() {
1956         check_assist(
1957             extract_function,
1958             r#"
1959 fn foo() {
1960     $0for v in &[0, 1] { }$0
1961 }
1962 "#,
1963             r#"
1964 fn foo() {
1965     fun_name();
1966 }
1967
1968 fn $0fun_name() {
1969     for v in &[0, 1] { }
1970 }
1971 "#,
1972         );
1973     }
1974
1975     #[test]
1976     fn no_args_from_loop_unit() {
1977         check_assist(
1978             extract_function,
1979             r#"
1980 fn foo() {
1981     $0loop {
1982         let m = 1;
1983     }$0
1984 }
1985 "#,
1986             r#"
1987 fn foo() {
1988     fun_name()
1989 }
1990
1991 fn $0fun_name() -> ! {
1992     loop {
1993         let m = 1;
1994     }
1995 }
1996 "#,
1997         );
1998     }
1999
2000     #[test]
2001     fn no_args_from_loop_with_return() {
2002         check_assist(
2003             extract_function,
2004             r#"
2005 fn foo() {
2006     let v = $0loop {
2007         let m = 1;
2008         break m;
2009     }$0;
2010 }
2011 "#,
2012             r#"
2013 fn foo() {
2014     let v = fun_name();
2015 }
2016
2017 fn $0fun_name() -> i32 {
2018     loop {
2019         let m = 1;
2020         break m;
2021     }
2022 }
2023 "#,
2024         );
2025     }
2026
2027     #[test]
2028     fn no_args_from_match() {
2029         check_assist(
2030             extract_function,
2031             r#"
2032 fn foo() {
2033     let v: i32 = $0match Some(1) {
2034         Some(x) => x,
2035         None => 0,
2036     }$0;
2037 }
2038 "#,
2039             r#"
2040 fn foo() {
2041     let v: i32 = fun_name();
2042 }
2043
2044 fn $0fun_name() -> i32 {
2045     match Some(1) {
2046         Some(x) => x,
2047         None => 0,
2048     }
2049 }
2050 "#,
2051         );
2052     }
2053
2054     #[test]
2055     fn extract_partial_block_single_line() {
2056         check_assist(
2057             extract_function,
2058             r#"
2059 fn foo() {
2060     let n = 1;
2061     let mut v = $0n * n;$0
2062     v += 1;
2063 }
2064 "#,
2065             r#"
2066 fn foo() {
2067     let n = 1;
2068     let mut v = fun_name(n);
2069     v += 1;
2070 }
2071
2072 fn $0fun_name(n: i32) -> i32 {
2073     let mut v = n * n;
2074     v
2075 }
2076 "#,
2077         );
2078     }
2079
2080     #[test]
2081     fn extract_partial_block() {
2082         check_assist(
2083             extract_function,
2084             r#"
2085 fn foo() {
2086     let m = 2;
2087     let n = 1;
2088     let mut v = m $0* n;
2089     let mut w = 3;$0
2090     v += 1;
2091     w += 1;
2092 }
2093 "#,
2094             r#"
2095 fn foo() {
2096     let m = 2;
2097     let n = 1;
2098     let (mut v, mut w) = fun_name(m, n);
2099     v += 1;
2100     w += 1;
2101 }
2102
2103 fn $0fun_name(m: i32, n: i32) -> (i32, i32) {
2104     let mut v = m * n;
2105     let mut w = 3;
2106     (v, w)
2107 }
2108 "#,
2109         );
2110     }
2111
2112     #[test]
2113     fn argument_form_expr() {
2114         check_assist(
2115             extract_function,
2116             r#"
2117 fn foo() -> u32 {
2118     let n = 2;
2119     $0n+2$0
2120 }
2121 "#,
2122             r#"
2123 fn foo() -> u32 {
2124     let n = 2;
2125     fun_name(n)
2126 }
2127
2128 fn $0fun_name(n: u32) -> u32 {
2129     n+2
2130 }
2131 "#,
2132         )
2133     }
2134
2135     #[test]
2136     fn argument_used_twice_form_expr() {
2137         check_assist(
2138             extract_function,
2139             r#"
2140 fn foo() -> u32 {
2141     let n = 2;
2142     $0n+n$0
2143 }
2144 "#,
2145             r#"
2146 fn foo() -> u32 {
2147     let n = 2;
2148     fun_name(n)
2149 }
2150
2151 fn $0fun_name(n: u32) -> u32 {
2152     n+n
2153 }
2154 "#,
2155         )
2156     }
2157
2158     #[test]
2159     fn two_arguments_form_expr() {
2160         check_assist(
2161             extract_function,
2162             r#"
2163 fn foo() -> u32 {
2164     let n = 2;
2165     let m = 3;
2166     $0n+n*m$0
2167 }
2168 "#,
2169             r#"
2170 fn foo() -> u32 {
2171     let n = 2;
2172     let m = 3;
2173     fun_name(n, m)
2174 }
2175
2176 fn $0fun_name(n: u32, m: u32) -> u32 {
2177     n+n*m
2178 }
2179 "#,
2180         )
2181     }
2182
2183     #[test]
2184     fn argument_and_locals() {
2185         check_assist(
2186             extract_function,
2187             r#"
2188 fn foo() -> u32 {
2189     let n = 2;
2190     $0let m = 1;
2191     n + m$0
2192 }
2193 "#,
2194             r#"
2195 fn foo() -> u32 {
2196     let n = 2;
2197     fun_name(n)
2198 }
2199
2200 fn $0fun_name(n: u32) -> u32 {
2201     let m = 1;
2202     n + m
2203 }
2204 "#,
2205         )
2206     }
2207
2208     #[test]
2209     fn in_comment_is_not_applicable() {
2210         cov_mark::check!(extract_function_in_comment_is_not_applicable);
2211         check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
2212     }
2213
2214     #[test]
2215     fn part_of_expr_stmt() {
2216         check_assist(
2217             extract_function,
2218             r#"
2219 fn foo() {
2220     $01$0 + 1;
2221 }
2222 "#,
2223             r#"
2224 fn foo() {
2225     fun_name() + 1;
2226 }
2227
2228 fn $0fun_name() -> i32 {
2229     1
2230 }
2231 "#,
2232         );
2233     }
2234
2235     #[test]
2236     fn function_expr() {
2237         check_assist(
2238             extract_function,
2239             r#"
2240 fn foo() {
2241     $0bar(1 + 1)$0
2242 }
2243 "#,
2244             r#"
2245 fn foo() {
2246     fun_name();
2247 }
2248
2249 fn $0fun_name() {
2250     bar(1 + 1)
2251 }
2252 "#,
2253         )
2254     }
2255
2256     #[test]
2257     fn extract_from_nested() {
2258         check_assist(
2259             extract_function,
2260             r#"
2261 fn main() {
2262     let x = true;
2263     let tuple = match x {
2264         true => ($02 + 2$0, true)
2265         _ => (0, false)
2266     };
2267 }
2268 "#,
2269             r#"
2270 fn main() {
2271     let x = true;
2272     let tuple = match x {
2273         true => (fun_name(), true)
2274         _ => (0, false)
2275     };
2276 }
2277
2278 fn $0fun_name() -> i32 {
2279     2 + 2
2280 }
2281 "#,
2282         );
2283     }
2284
2285     #[test]
2286     fn param_from_closure() {
2287         check_assist(
2288             extract_function,
2289             r#"
2290 fn main() {
2291     let lambda = |x: u32| $0x * 2$0;
2292 }
2293 "#,
2294             r#"
2295 fn main() {
2296     let lambda = |x: u32| fun_name(x);
2297 }
2298
2299 fn $0fun_name(x: u32) -> u32 {
2300     x * 2
2301 }
2302 "#,
2303         );
2304     }
2305
2306     #[test]
2307     fn extract_return_stmt() {
2308         check_assist(
2309             extract_function,
2310             r#"
2311 fn foo() -> u32 {
2312     $0return 2 + 2$0;
2313 }
2314 "#,
2315             r#"
2316 fn foo() -> u32 {
2317     return fun_name();
2318 }
2319
2320 fn $0fun_name() -> u32 {
2321     2 + 2
2322 }
2323 "#,
2324         );
2325     }
2326
2327     #[test]
2328     fn does_not_add_extra_whitespace() {
2329         check_assist(
2330             extract_function,
2331             r#"
2332 fn foo() -> u32 {
2333
2334
2335     $0return 2 + 2$0;
2336 }
2337 "#,
2338             r#"
2339 fn foo() -> u32 {
2340
2341
2342     return fun_name();
2343 }
2344
2345 fn $0fun_name() -> u32 {
2346     2 + 2
2347 }
2348 "#,
2349         );
2350     }
2351
2352     #[test]
2353     fn break_stmt() {
2354         check_assist(
2355             extract_function,
2356             r#"
2357 fn main() {
2358     let result = loop {
2359         $0break 2 + 2$0;
2360     };
2361 }
2362 "#,
2363             r#"
2364 fn main() {
2365     let result = loop {
2366         break fun_name();
2367     };
2368 }
2369
2370 fn $0fun_name() -> i32 {
2371     2 + 2
2372 }
2373 "#,
2374         );
2375     }
2376
2377     #[test]
2378     fn extract_cast() {
2379         check_assist(
2380             extract_function,
2381             r#"
2382 fn main() {
2383     let v = $00f32 as u32$0;
2384 }
2385 "#,
2386             r#"
2387 fn main() {
2388     let v = fun_name();
2389 }
2390
2391 fn $0fun_name() -> u32 {
2392     0f32 as u32
2393 }
2394 "#,
2395         );
2396     }
2397
2398     #[test]
2399     fn return_not_applicable() {
2400         check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2401     }
2402
2403     #[test]
2404     fn method_to_freestanding() {
2405         check_assist(
2406             extract_function,
2407             r#"
2408 struct S;
2409
2410 impl S {
2411     fn foo(&self) -> i32 {
2412         $01+1$0
2413     }
2414 }
2415 "#,
2416             r#"
2417 struct S;
2418
2419 impl S {
2420     fn foo(&self) -> i32 {
2421         fun_name()
2422     }
2423 }
2424
2425 fn $0fun_name() -> i32 {
2426     1+1
2427 }
2428 "#,
2429         );
2430     }
2431
2432     #[test]
2433     fn method_with_reference() {
2434         check_assist(
2435             extract_function,
2436             r#"
2437 struct S { f: i32 };
2438
2439 impl S {
2440     fn foo(&self) -> i32 {
2441         $0self.f+self.f$0
2442     }
2443 }
2444 "#,
2445             r#"
2446 struct S { f: i32 };
2447
2448 impl S {
2449     fn foo(&self) -> i32 {
2450         self.fun_name()
2451     }
2452
2453     fn $0fun_name(&self) -> i32 {
2454         self.f+self.f
2455     }
2456 }
2457 "#,
2458         );
2459     }
2460
2461     #[test]
2462     fn method_with_mut() {
2463         check_assist(
2464             extract_function,
2465             r#"
2466 struct S { f: i32 };
2467
2468 impl S {
2469     fn foo(&mut self) {
2470         $0self.f += 1;$0
2471     }
2472 }
2473 "#,
2474             r#"
2475 struct S { f: i32 };
2476
2477 impl S {
2478     fn foo(&mut self) {
2479         self.fun_name();
2480     }
2481
2482     fn $0fun_name(&mut self) {
2483         self.f += 1;
2484     }
2485 }
2486 "#,
2487         );
2488     }
2489
2490     #[test]
2491     fn variable_defined_inside_and_used_after_no_ret() {
2492         check_assist(
2493             extract_function,
2494             r#"
2495 fn foo() {
2496     let n = 1;
2497     $0let k = n * n;$0
2498     let m = k + 1;
2499 }
2500 "#,
2501             r#"
2502 fn foo() {
2503     let n = 1;
2504     let k = fun_name(n);
2505     let m = k + 1;
2506 }
2507
2508 fn $0fun_name(n: i32) -> i32 {
2509     let k = n * n;
2510     k
2511 }
2512 "#,
2513         );
2514     }
2515
2516     #[test]
2517     fn variable_defined_inside_and_used_after_mutably_no_ret() {
2518         check_assist(
2519             extract_function,
2520             r#"
2521 fn foo() {
2522     let n = 1;
2523     $0let mut k = n * n;$0
2524     k += 1;
2525 }
2526 "#,
2527             r#"
2528 fn foo() {
2529     let n = 1;
2530     let mut k = fun_name(n);
2531     k += 1;
2532 }
2533
2534 fn $0fun_name(n: i32) -> i32 {
2535     let mut k = n * n;
2536     k
2537 }
2538 "#,
2539         );
2540     }
2541
2542     #[test]
2543     fn two_variables_defined_inside_and_used_after_no_ret() {
2544         check_assist(
2545             extract_function,
2546             r#"
2547 fn foo() {
2548     let n = 1;
2549     $0let k = n * n;
2550     let m = k + 2;$0
2551     let h = k + m;
2552 }
2553 "#,
2554             r#"
2555 fn foo() {
2556     let n = 1;
2557     let (k, m) = fun_name(n);
2558     let h = k + m;
2559 }
2560
2561 fn $0fun_name(n: i32) -> (i32, i32) {
2562     let k = n * n;
2563     let m = k + 2;
2564     (k, m)
2565 }
2566 "#,
2567         );
2568     }
2569
2570     #[test]
2571     fn multi_variables_defined_inside_and_used_after_mutably_no_ret() {
2572         check_assist(
2573             extract_function,
2574             r#"
2575 fn foo() {
2576     let n = 1;
2577     $0let mut k = n * n;
2578     let mut m = k + 2;
2579     let mut o = m + 3;
2580     o += 1;$0
2581     k += o;
2582     m = 1;
2583 }
2584 "#,
2585             r#"
2586 fn foo() {
2587     let n = 1;
2588     let (mut k, mut m, o) = fun_name(n);
2589     k += o;
2590     m = 1;
2591 }
2592
2593 fn $0fun_name(n: i32) -> (i32, i32, i32) {
2594     let mut k = n * n;
2595     let mut m = k + 2;
2596     let mut o = m + 3;
2597     o += 1;
2598     (k, m, o)
2599 }
2600 "#,
2601         );
2602     }
2603
2604     #[test]
2605     fn nontrivial_patterns_define_variables() {
2606         check_assist(
2607             extract_function,
2608             r#"
2609 struct Counter(i32);
2610 fn foo() {
2611     $0let Counter(n) = Counter(0);$0
2612     let m = n;
2613 }
2614 "#,
2615             r#"
2616 struct Counter(i32);
2617 fn foo() {
2618     let n = fun_name();
2619     let m = n;
2620 }
2621
2622 fn $0fun_name() -> i32 {
2623     let Counter(n) = Counter(0);
2624     n
2625 }
2626 "#,
2627         );
2628     }
2629
2630     #[test]
2631     fn struct_with_two_fields_pattern_define_variables() {
2632         check_assist(
2633             extract_function,
2634             r#"
2635 struct Counter { n: i32, m: i32 };
2636 fn foo() {
2637     $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
2638     let h = n + k;
2639 }
2640 "#,
2641             r#"
2642 struct Counter { n: i32, m: i32 };
2643 fn foo() {
2644     let (n, k) = fun_name();
2645     let h = n + k;
2646 }
2647
2648 fn $0fun_name() -> (i32, i32) {
2649     let Counter { n, m: k } = Counter { n: 1, m: 2 };
2650     (n, k)
2651 }
2652 "#,
2653         );
2654     }
2655
2656     #[test]
2657     fn mut_var_from_outer_scope() {
2658         check_assist(
2659             extract_function,
2660             r#"
2661 fn foo() {
2662     let mut n = 1;
2663     $0n += 1;$0
2664     let m = n + 1;
2665 }
2666 "#,
2667             r#"
2668 fn foo() {
2669     let mut n = 1;
2670     fun_name(&mut n);
2671     let m = n + 1;
2672 }
2673
2674 fn $0fun_name(n: &mut i32) {
2675     *n += 1;
2676 }
2677 "#,
2678         );
2679     }
2680
2681     #[test]
2682     fn mut_field_from_outer_scope() {
2683         check_assist(
2684             extract_function,
2685             r#"
2686 struct C { n: i32 }
2687 fn foo() {
2688     let mut c = C { n: 0 };
2689     $0c.n += 1;$0
2690     let m = c.n + 1;
2691 }
2692 "#,
2693             r#"
2694 struct C { n: i32 }
2695 fn foo() {
2696     let mut c = C { n: 0 };
2697     fun_name(&mut c);
2698     let m = c.n + 1;
2699 }
2700
2701 fn $0fun_name(c: &mut C) {
2702     c.n += 1;
2703 }
2704 "#,
2705         );
2706     }
2707
2708     #[test]
2709     fn mut_nested_field_from_outer_scope() {
2710         check_assist(
2711             extract_function,
2712             r#"
2713 struct P { n: i32}
2714 struct C { p: P }
2715 fn foo() {
2716     let mut c = C { p: P { n: 0 } };
2717     let mut v = C { p: P { n: 0 } };
2718     let u = C { p: P { n: 0 } };
2719     $0c.p.n += u.p.n;
2720     let r = &mut v.p.n;$0
2721     let m = c.p.n + v.p.n + u.p.n;
2722 }
2723 "#,
2724             r#"
2725 struct P { n: i32}
2726 struct C { p: P }
2727 fn foo() {
2728     let mut c = C { p: P { n: 0 } };
2729     let mut v = C { p: P { n: 0 } };
2730     let u = C { p: P { n: 0 } };
2731     fun_name(&mut c, &u, &mut v);
2732     let m = c.p.n + v.p.n + u.p.n;
2733 }
2734
2735 fn $0fun_name(c: &mut C, u: &C, v: &mut C) {
2736     c.p.n += u.p.n;
2737     let r = &mut v.p.n;
2738 }
2739 "#,
2740         );
2741     }
2742
2743     #[test]
2744     fn mut_param_many_usages_stmt() {
2745         check_assist(
2746             extract_function,
2747             r#"
2748 fn bar(k: i32) {}
2749 trait I: Copy {
2750     fn succ(&self) -> Self;
2751     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2752 }
2753 impl I for i32 {
2754     fn succ(&self) -> Self { *self + 1 }
2755 }
2756 fn foo() {
2757     let mut n = 1;
2758     $0n += n;
2759     bar(n);
2760     bar(n+1);
2761     bar(n*n);
2762     bar(&n);
2763     n.inc();
2764     let v = &mut n;
2765     *v = v.succ();
2766     n.succ();$0
2767     let m = n + 1;
2768 }
2769 "#,
2770             r#"
2771 fn bar(k: i32) {}
2772 trait I: Copy {
2773     fn succ(&self) -> Self;
2774     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2775 }
2776 impl I for i32 {
2777     fn succ(&self) -> Self { *self + 1 }
2778 }
2779 fn foo() {
2780     let mut n = 1;
2781     fun_name(&mut n);
2782     let m = n + 1;
2783 }
2784
2785 fn $0fun_name(n: &mut i32) {
2786     *n += *n;
2787     bar(*n);
2788     bar(*n+1);
2789     bar(*n**n);
2790     bar(&*n);
2791     n.inc();
2792     let v = n;
2793     *v = v.succ();
2794     n.succ();
2795 }
2796 "#,
2797         );
2798     }
2799
2800     #[test]
2801     fn mut_param_many_usages_expr() {
2802         check_assist(
2803             extract_function,
2804             r#"
2805 fn bar(k: i32) {}
2806 trait I: Copy {
2807     fn succ(&self) -> Self;
2808     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2809 }
2810 impl I for i32 {
2811     fn succ(&self) -> Self { *self + 1 }
2812 }
2813 fn foo() {
2814     let mut n = 1;
2815     $0{
2816         n += n;
2817         bar(n);
2818         bar(n+1);
2819         bar(n*n);
2820         bar(&n);
2821         n.inc();
2822         let v = &mut n;
2823         *v = v.succ();
2824         n.succ();
2825     }$0
2826     let m = n + 1;
2827 }
2828 "#,
2829             r#"
2830 fn bar(k: i32) {}
2831 trait I: Copy {
2832     fn succ(&self) -> Self;
2833     fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
2834 }
2835 impl I for i32 {
2836     fn succ(&self) -> Self { *self + 1 }
2837 }
2838 fn foo() {
2839     let mut n = 1;
2840     fun_name(&mut n);
2841     let m = n + 1;
2842 }
2843
2844 fn $0fun_name(n: &mut i32) {
2845     *n += *n;
2846     bar(*n);
2847     bar(*n+1);
2848     bar(*n**n);
2849     bar(&*n);
2850     n.inc();
2851     let v = n;
2852     *v = v.succ();
2853     n.succ();
2854 }
2855 "#,
2856         );
2857     }
2858
2859     #[test]
2860     fn mut_param_by_value() {
2861         check_assist(
2862             extract_function,
2863             r#"
2864 fn foo() {
2865     let mut n = 1;
2866     $0n += 1;$0
2867 }
2868 "#,
2869             r"
2870 fn foo() {
2871     let mut n = 1;
2872     fun_name(n);
2873 }
2874
2875 fn $0fun_name(mut n: i32) {
2876     n += 1;
2877 }
2878 ",
2879         );
2880     }
2881
2882     #[test]
2883     fn mut_param_because_of_mut_ref() {
2884         check_assist(
2885             extract_function,
2886             r#"
2887 fn foo() {
2888     let mut n = 1;
2889     $0let v = &mut n;
2890     *v += 1;$0
2891     let k = n;
2892 }
2893 "#,
2894             r#"
2895 fn foo() {
2896     let mut n = 1;
2897     fun_name(&mut n);
2898     let k = n;
2899 }
2900
2901 fn $0fun_name(n: &mut i32) {
2902     let v = n;
2903     *v += 1;
2904 }
2905 "#,
2906         );
2907     }
2908
2909     #[test]
2910     fn mut_param_by_value_because_of_mut_ref() {
2911         check_assist(
2912             extract_function,
2913             r"
2914 fn foo() {
2915     let mut n = 1;
2916     $0let v = &mut n;
2917     *v += 1;$0
2918 }
2919 ",
2920             r#"
2921 fn foo() {
2922     let mut n = 1;
2923     fun_name(n);
2924 }
2925
2926 fn $0fun_name(mut n: i32) {
2927     let v = &mut n;
2928     *v += 1;
2929 }
2930 "#,
2931         );
2932     }
2933
2934     #[test]
2935     fn mut_method_call() {
2936         check_assist(
2937             extract_function,
2938             r#"
2939 trait I {
2940     fn inc(&mut self);
2941 }
2942 impl I for i32 {
2943     fn inc(&mut self) { *self += 1 }
2944 }
2945 fn foo() {
2946     let mut n = 1;
2947     $0n.inc();$0
2948 }
2949 "#,
2950             r#"
2951 trait I {
2952     fn inc(&mut self);
2953 }
2954 impl I for i32 {
2955     fn inc(&mut self) { *self += 1 }
2956 }
2957 fn foo() {
2958     let mut n = 1;
2959     fun_name(n);
2960 }
2961
2962 fn $0fun_name(mut n: i32) {
2963     n.inc();
2964 }
2965 "#,
2966         );
2967     }
2968
2969     #[test]
2970     fn shared_method_call() {
2971         check_assist(
2972             extract_function,
2973             r#"
2974 trait I {
2975     fn succ(&self);
2976 }
2977 impl I for i32 {
2978     fn succ(&self) { *self + 1 }
2979 }
2980 fn foo() {
2981     let mut n = 1;
2982     $0n.succ();$0
2983 }
2984 "#,
2985             r"
2986 trait I {
2987     fn succ(&self);
2988 }
2989 impl I for i32 {
2990     fn succ(&self) { *self + 1 }
2991 }
2992 fn foo() {
2993     let mut n = 1;
2994     fun_name(n);
2995 }
2996
2997 fn $0fun_name(n: i32) {
2998     n.succ();
2999 }
3000 ",
3001         );
3002     }
3003
3004     #[test]
3005     fn mut_method_call_with_other_receiver() {
3006         check_assist(
3007             extract_function,
3008             r#"
3009 trait I {
3010     fn inc(&mut self, n: i32);
3011 }
3012 impl I for i32 {
3013     fn inc(&mut self, n: i32) { *self += n }
3014 }
3015 fn foo() {
3016     let mut n = 1;
3017     $0let mut m = 2;
3018     m.inc(n);$0
3019 }
3020 "#,
3021             r"
3022 trait I {
3023     fn inc(&mut self, n: i32);
3024 }
3025 impl I for i32 {
3026     fn inc(&mut self, n: i32) { *self += n }
3027 }
3028 fn foo() {
3029     let mut n = 1;
3030     fun_name(n);
3031 }
3032
3033 fn $0fun_name(n: i32) {
3034     let mut m = 2;
3035     m.inc(n);
3036 }
3037 ",
3038         );
3039     }
3040
3041     #[test]
3042     fn non_copy_without_usages_after() {
3043         check_assist(
3044             extract_function,
3045             r#"
3046 struct Counter(i32);
3047 fn foo() {
3048     let c = Counter(0);
3049     $0let n = c.0;$0
3050 }
3051 "#,
3052             r"
3053 struct Counter(i32);
3054 fn foo() {
3055     let c = Counter(0);
3056     fun_name(c);
3057 }
3058
3059 fn $0fun_name(c: Counter) {
3060     let n = c.0;
3061 }
3062 ",
3063         );
3064     }
3065
3066     #[test]
3067     fn non_copy_used_after() {
3068         check_assist(
3069             extract_function,
3070             r"
3071 struct Counter(i32);
3072 fn foo() {
3073     let c = Counter(0);
3074     $0let n = c.0;$0
3075     let m = c.0;
3076 }
3077 ",
3078             r#"
3079 struct Counter(i32);
3080 fn foo() {
3081     let c = Counter(0);
3082     fun_name(&c);
3083     let m = c.0;
3084 }
3085
3086 fn $0fun_name(c: &Counter) {
3087     let n = c.0;
3088 }
3089 "#,
3090         );
3091     }
3092
3093     #[test]
3094     fn copy_used_after() {
3095         check_assist(
3096             extract_function,
3097             r#"
3098 //- minicore: copy
3099 fn foo() {
3100     let n = 0;
3101     $0let m = n;$0
3102     let k = n;
3103 }
3104 "#,
3105             r#"
3106 fn foo() {
3107     let n = 0;
3108     fun_name(n);
3109     let k = n;
3110 }
3111
3112 fn $0fun_name(n: i32) {
3113     let m = n;
3114 }
3115 "#,
3116         )
3117     }
3118
3119     #[test]
3120     fn copy_custom_used_after() {
3121         check_assist(
3122             extract_function,
3123             r#"
3124 //- minicore: copy, derive
3125 #[derive(Clone, Copy)]
3126 struct Counter(i32);
3127 fn foo() {
3128     let c = Counter(0);
3129     $0let n = c.0;$0
3130     let m = c.0;
3131 }
3132 "#,
3133             r#"
3134 #[derive(Clone, Copy)]
3135 struct Counter(i32);
3136 fn foo() {
3137     let c = Counter(0);
3138     fun_name(c);
3139     let m = c.0;
3140 }
3141
3142 fn $0fun_name(c: Counter) {
3143     let n = c.0;
3144 }
3145 "#,
3146         );
3147     }
3148
3149     #[test]
3150     fn indented_stmts() {
3151         check_assist(
3152             extract_function,
3153             r#"
3154 fn foo() {
3155     if true {
3156         loop {
3157             $0let n = 1;
3158             let m = 2;$0
3159         }
3160     }
3161 }
3162 "#,
3163             r#"
3164 fn foo() {
3165     if true {
3166         loop {
3167             fun_name();
3168         }
3169     }
3170 }
3171
3172 fn $0fun_name() {
3173     let n = 1;
3174     let m = 2;
3175 }
3176 "#,
3177         );
3178     }
3179
3180     #[test]
3181     fn indented_stmts_inside_mod() {
3182         check_assist(
3183             extract_function,
3184             r#"
3185 mod bar {
3186     fn foo() {
3187         if true {
3188             loop {
3189                 $0let n = 1;
3190                 let m = 2;$0
3191             }
3192         }
3193     }
3194 }
3195 "#,
3196             r#"
3197 mod bar {
3198     fn foo() {
3199         if true {
3200             loop {
3201                 fun_name();
3202             }
3203         }
3204     }
3205
3206     fn $0fun_name() {
3207         let n = 1;
3208         let m = 2;
3209     }
3210 }
3211 "#,
3212         );
3213     }
3214
3215     #[test]
3216     fn break_loop() {
3217         check_assist(
3218             extract_function,
3219             r#"
3220 //- minicore: option
3221 fn foo() {
3222     loop {
3223         let n = 1;
3224         $0let m = n + 1;
3225         break;
3226         let k = 2;$0
3227         let h = 1 + k;
3228     }
3229 }
3230 "#,
3231             r#"
3232 fn foo() {
3233     loop {
3234         let n = 1;
3235         let k = match fun_name(n) {
3236             Some(value) => value,
3237             None => break,
3238         };
3239         let h = 1 + k;
3240     }
3241 }
3242
3243 fn $0fun_name(n: i32) -> Option<i32> {
3244     let m = n + 1;
3245     return None;
3246     let k = 2;
3247     Some(k)
3248 }
3249 "#,
3250         );
3251     }
3252
3253     #[test]
3254     fn return_to_parent() {
3255         check_assist(
3256             extract_function,
3257             r#"
3258 //- minicore: copy, result
3259 fn foo() -> i64 {
3260     let n = 1;
3261     $0let m = n + 1;
3262     return 1;
3263     let k = 2;$0
3264     (n + k) as i64
3265 }
3266 "#,
3267             r#"
3268 fn foo() -> i64 {
3269     let n = 1;
3270     let k = match fun_name(n) {
3271         Ok(value) => value,
3272         Err(value) => return value,
3273     };
3274     (n + k) as i64
3275 }
3276
3277 fn $0fun_name(n: i32) -> Result<i32, i64> {
3278     let m = n + 1;
3279     return Err(1);
3280     let k = 2;
3281     Ok(k)
3282 }
3283 "#,
3284         );
3285     }
3286
3287     #[test]
3288     fn break_and_continue() {
3289         cov_mark::check!(external_control_flow_break_and_continue);
3290         check_assist_not_applicable(
3291             extract_function,
3292             r#"
3293 fn foo() {
3294     loop {
3295         let n = 1;
3296         $0let m = n + 1;
3297         break;
3298         let k = 2;
3299         continue;
3300         let k = k + 1;$0
3301         let r = n + k;
3302     }
3303 }
3304 "#,
3305         );
3306     }
3307
3308     #[test]
3309     fn return_and_break() {
3310         cov_mark::check!(external_control_flow_return_and_bc);
3311         check_assist_not_applicable(
3312             extract_function,
3313             r#"
3314 fn foo() {
3315     loop {
3316         let n = 1;
3317         $0let m = n + 1;
3318         break;
3319         let k = 2;
3320         return;
3321         let k = k + 1;$0
3322         let r = n + k;
3323     }
3324 }
3325 "#,
3326         );
3327     }
3328
3329     #[test]
3330     fn break_loop_with_if() {
3331         check_assist(
3332             extract_function,
3333             r#"
3334 //- minicore: try
3335 fn foo() {
3336     loop {
3337         let mut n = 1;
3338         $0let m = n + 1;
3339         break;
3340         n += m;$0
3341         let h = 1 + n;
3342     }
3343 }
3344 "#,
3345             r#"
3346 use core::ops::ControlFlow;
3347
3348 fn foo() {
3349     loop {
3350         let mut n = 1;
3351         if let ControlFlow::Break(_) = fun_name(&mut n) {
3352             break;
3353         }
3354         let h = 1 + n;
3355     }
3356 }
3357
3358 fn $0fun_name(n: &mut i32) -> ControlFlow<()> {
3359     let m = *n + 1;
3360     return ControlFlow::Break(());
3361     *n += m;
3362     ControlFlow::Continue(())
3363 }
3364 "#,
3365         );
3366     }
3367
3368     #[test]
3369     fn break_loop_nested() {
3370         check_assist(
3371             extract_function,
3372             r#"
3373 //- minicore: try
3374 fn foo() {
3375     loop {
3376         let mut n = 1;
3377         $0let m = n + 1;
3378         if m == 42 {
3379             break;
3380         }$0
3381         let h = 1;
3382     }
3383 }
3384 "#,
3385             r#"
3386 use core::ops::ControlFlow;
3387
3388 fn foo() {
3389     loop {
3390         let mut n = 1;
3391         if let ControlFlow::Break(_) = fun_name(n) {
3392             break;
3393         }
3394         let h = 1;
3395     }
3396 }
3397
3398 fn $0fun_name(n: i32) -> ControlFlow<()> {
3399     let m = n + 1;
3400     if m == 42 {
3401         return ControlFlow::Break(());
3402     }
3403     ControlFlow::Continue(())
3404 }
3405 "#,
3406         );
3407     }
3408
3409     #[test]
3410     fn return_from_nested_loop() {
3411         check_assist(
3412             extract_function,
3413             r#"
3414 fn foo() {
3415     loop {
3416         let n = 1;$0
3417         let k = 1;
3418         loop {
3419             return;
3420         }
3421         let m = k + 1;$0
3422         let h = 1 + m;
3423     }
3424 }
3425 "#,
3426             r#"
3427 fn foo() {
3428     loop {
3429         let n = 1;
3430         let m = match fun_name() {
3431             Some(value) => value,
3432             None => return,
3433         };
3434         let h = 1 + m;
3435     }
3436 }
3437
3438 fn $0fun_name() -> Option<i32> {
3439     let k = 1;
3440     loop {
3441         return None;
3442     }
3443     let m = k + 1;
3444     Some(m)
3445 }
3446 "#,
3447         );
3448     }
3449
3450     #[test]
3451     fn break_from_nested_loop() {
3452         check_assist(
3453             extract_function,
3454             r#"
3455 fn foo() {
3456     loop {
3457         let n = 1;
3458         $0let k = 1;
3459         loop {
3460             break;
3461         }
3462         let m = k + 1;$0
3463         let h = 1 + m;
3464     }
3465 }
3466 "#,
3467             r#"
3468 fn foo() {
3469     loop {
3470         let n = 1;
3471         let m = fun_name();
3472         let h = 1 + m;
3473     }
3474 }
3475
3476 fn $0fun_name() -> i32 {
3477     let k = 1;
3478     loop {
3479         break;
3480     }
3481     let m = k + 1;
3482     m
3483 }
3484 "#,
3485         );
3486     }
3487
3488     #[test]
3489     fn break_from_nested_and_outer_loops() {
3490         check_assist(
3491             extract_function,
3492             r#"
3493 fn foo() {
3494     loop {
3495         let n = 1;
3496         $0let k = 1;
3497         loop {
3498             break;
3499         }
3500         if k == 42 {
3501             break;
3502         }
3503         let m = k + 1;$0
3504         let h = 1 + m;
3505     }
3506 }
3507 "#,
3508             r#"
3509 fn foo() {
3510     loop {
3511         let n = 1;
3512         let m = match fun_name() {
3513             Some(value) => value,
3514             None => break,
3515         };
3516         let h = 1 + m;
3517     }
3518 }
3519
3520 fn $0fun_name() -> Option<i32> {
3521     let k = 1;
3522     loop {
3523         break;
3524     }
3525     if k == 42 {
3526         return None;
3527     }
3528     let m = k + 1;
3529     Some(m)
3530 }
3531 "#,
3532         );
3533     }
3534
3535     #[test]
3536     fn return_from_nested_fn() {
3537         check_assist(
3538             extract_function,
3539             r#"
3540 fn foo() {
3541     loop {
3542         let n = 1;
3543         $0let k = 1;
3544         fn test() {
3545             return;
3546         }
3547         let m = k + 1;$0
3548         let h = 1 + m;
3549     }
3550 }
3551 "#,
3552             r#"
3553 fn foo() {
3554     loop {
3555         let n = 1;
3556         let m = fun_name();
3557         let h = 1 + m;
3558     }
3559 }
3560
3561 fn $0fun_name() -> i32 {
3562     let k = 1;
3563     fn test() {
3564         return;
3565     }
3566     let m = k + 1;
3567     m
3568 }
3569 "#,
3570         );
3571     }
3572
3573     #[test]
3574     fn break_with_value() {
3575         check_assist(
3576             extract_function,
3577             r#"
3578 fn foo() -> i32 {
3579     loop {
3580         let n = 1;
3581         $0let k = 1;
3582         if k == 42 {
3583             break 3;
3584         }
3585         let m = k + 1;$0
3586         let h = 1;
3587     }
3588 }
3589 "#,
3590             r#"
3591 fn foo() -> i32 {
3592     loop {
3593         let n = 1;
3594         if let Some(value) = fun_name() {
3595             break value;
3596         }
3597         let h = 1;
3598     }
3599 }
3600
3601 fn $0fun_name() -> Option<i32> {
3602     let k = 1;
3603     if k == 42 {
3604         return Some(3);
3605     }
3606     let m = k + 1;
3607     None
3608 }
3609 "#,
3610         );
3611     }
3612
3613     #[test]
3614     fn break_with_value_and_return() {
3615         check_assist(
3616             extract_function,
3617             r#"
3618 fn foo() -> i64 {
3619     loop {
3620         let n = 1;$0
3621         let k = 1;
3622         if k == 42 {
3623             break 3;
3624         }
3625         let m = k + 1;$0
3626         let h = 1 + m;
3627     }
3628 }
3629 "#,
3630             r#"
3631 fn foo() -> i64 {
3632     loop {
3633         let n = 1;
3634         let m = match fun_name() {
3635             Ok(value) => value,
3636             Err(value) => break value,
3637         };
3638         let h = 1 + m;
3639     }
3640 }
3641
3642 fn $0fun_name() -> Result<i32, i64> {
3643     let k = 1;
3644     if k == 42 {
3645         return Err(3);
3646     }
3647     let m = k + 1;
3648     Ok(m)
3649 }
3650 "#,
3651         );
3652     }
3653
3654     #[test]
3655     fn try_option() {
3656         check_assist(
3657             extract_function,
3658             r#"
3659 //- minicore: option
3660 fn bar() -> Option<i32> { None }
3661 fn foo() -> Option<()> {
3662     let n = bar()?;
3663     $0let k = foo()?;
3664     let m = k + 1;$0
3665     let h = 1 + m;
3666     Some(())
3667 }
3668 "#,
3669             r#"
3670 fn bar() -> Option<i32> { None }
3671 fn foo() -> Option<()> {
3672     let n = bar()?;
3673     let m = fun_name()?;
3674     let h = 1 + m;
3675     Some(())
3676 }
3677
3678 fn $0fun_name() -> Option<i32> {
3679     let k = foo()?;
3680     let m = k + 1;
3681     Some(m)
3682 }
3683 "#,
3684         );
3685     }
3686
3687     #[test]
3688     fn try_option_unit() {
3689         check_assist(
3690             extract_function,
3691             r#"
3692 //- minicore: option
3693 fn foo() -> Option<()> {
3694     let n = 1;
3695     $0let k = foo()?;
3696     let m = k + 1;$0
3697     let h = 1 + n;
3698     Some(())
3699 }
3700 "#,
3701             r#"
3702 fn foo() -> Option<()> {
3703     let n = 1;
3704     fun_name()?;
3705     let h = 1 + n;
3706     Some(())
3707 }
3708
3709 fn $0fun_name() -> Option<()> {
3710     let k = foo()?;
3711     let m = k + 1;
3712     Some(())
3713 }
3714 "#,
3715         );
3716     }
3717
3718     #[test]
3719     fn try_result() {
3720         check_assist(
3721             extract_function,
3722             r#"
3723 //- minicore: result
3724 fn foo() -> Result<(), i64> {
3725     let n = 1;
3726     $0let k = foo()?;
3727     let m = k + 1;$0
3728     let h = 1 + m;
3729     Ok(())
3730 }
3731 "#,
3732             r#"
3733 fn foo() -> Result<(), i64> {
3734     let n = 1;
3735     let m = fun_name()?;
3736     let h = 1 + m;
3737     Ok(())
3738 }
3739
3740 fn $0fun_name() -> Result<i32, i64> {
3741     let k = foo()?;
3742     let m = k + 1;
3743     Ok(m)
3744 }
3745 "#,
3746         );
3747     }
3748
3749     #[test]
3750     fn try_option_with_return() {
3751         check_assist(
3752             extract_function,
3753             r#"
3754 //- minicore: option
3755 fn foo() -> Option<()> {
3756     let n = 1;
3757     $0let k = foo()?;
3758     if k == 42 {
3759         return None;
3760     }
3761     let m = k + 1;$0
3762     let h = 1 + m;
3763     Some(())
3764 }
3765 "#,
3766             r#"
3767 fn foo() -> Option<()> {
3768     let n = 1;
3769     let m = fun_name()?;
3770     let h = 1 + m;
3771     Some(())
3772 }
3773
3774 fn $0fun_name() -> Option<i32> {
3775     let k = foo()?;
3776     if k == 42 {
3777         return None;
3778     }
3779     let m = k + 1;
3780     Some(m)
3781 }
3782 "#,
3783         );
3784     }
3785
3786     #[test]
3787     fn try_result_with_return() {
3788         check_assist(
3789             extract_function,
3790             r#"
3791 //- minicore: result
3792 fn foo() -> Result<(), i64> {
3793     let n = 1;
3794     $0let k = foo()?;
3795     if k == 42 {
3796         return Err(1);
3797     }
3798     let m = k + 1;$0
3799     let h = 1 + m;
3800     Ok(())
3801 }
3802 "#,
3803             r#"
3804 fn foo() -> Result<(), i64> {
3805     let n = 1;
3806     let m = fun_name()?;
3807     let h = 1 + m;
3808     Ok(())
3809 }
3810
3811 fn $0fun_name() -> Result<i32, i64> {
3812     let k = foo()?;
3813     if k == 42 {
3814         return Err(1);
3815     }
3816     let m = k + 1;
3817     Ok(m)
3818 }
3819 "#,
3820         );
3821     }
3822
3823     #[test]
3824     fn try_and_break() {
3825         cov_mark::check!(external_control_flow_try_and_bc);
3826         check_assist_not_applicable(
3827             extract_function,
3828             r#"
3829 //- minicore: option
3830 fn foo() -> Option<()> {
3831     loop {
3832         let n = Some(1);
3833         $0let m = n? + 1;
3834         break;
3835         let k = 2;
3836         let k = k + 1;$0
3837         let r = n + k;
3838     }
3839     Some(())
3840 }
3841 "#,
3842         );
3843     }
3844
3845     #[test]
3846     fn try_and_return_ok() {
3847         check_assist(
3848             extract_function,
3849             r#"
3850 //- minicore: result
3851 fn foo() -> Result<(), i64> {
3852     let n = 1;
3853     $0let k = foo()?;
3854     if k == 42 {
3855         return Ok(1);
3856     }
3857     let m = k + 1;$0
3858     let h = 1 + m;
3859     Ok(())
3860 }
3861 "#,
3862             r#"
3863 fn foo() -> Result<(), i64> {
3864     let n = 1;
3865     let m = fun_name()?;
3866     let h = 1 + m;
3867     Ok(())
3868 }
3869
3870 fn $0fun_name() -> Result<i32, i64> {
3871     let k = foo()?;
3872     if k == 42 {
3873         return Ok(1);
3874     }
3875     let m = k + 1;
3876     Ok(m)
3877 }
3878 "#,
3879         );
3880     }
3881
3882     #[test]
3883     fn param_usage_in_macro() {
3884         check_assist(
3885             extract_function,
3886             r#"
3887 macro_rules! m {
3888     ($val:expr) => { $val };
3889 }
3890
3891 fn foo() {
3892     let n = 1;
3893     $0let k = n * m!(n);$0
3894     let m = k + 1;
3895 }
3896 "#,
3897             r#"
3898 macro_rules! m {
3899     ($val:expr) => { $val };
3900 }
3901
3902 fn foo() {
3903     let n = 1;
3904     let k = fun_name(n);
3905     let m = k + 1;
3906 }
3907
3908 fn $0fun_name(n: i32) -> i32 {
3909     let k = n * m!(n);
3910     k
3911 }
3912 "#,
3913         );
3914     }
3915
3916     #[test]
3917     fn extract_with_await() {
3918         check_assist(
3919             extract_function,
3920             r#"
3921 fn main() {
3922     $0some_function().await;$0
3923 }
3924
3925 async fn some_function() {
3926
3927 }
3928 "#,
3929             r#"
3930 fn main() {
3931     fun_name().await;
3932 }
3933
3934 async fn $0fun_name() {
3935     some_function().await;
3936 }
3937
3938 async fn some_function() {
3939
3940 }
3941 "#,
3942         );
3943     }
3944
3945     #[test]
3946     fn extract_with_await_and_result_not_producing_match_expr() {
3947         check_assist(
3948             extract_function,
3949             r#"
3950 async fn foo() -> Result<(), ()> {
3951     $0async {}.await;
3952     Err(())?$0
3953 }
3954 "#,
3955             r#"
3956 async fn foo() -> Result<(), ()> {
3957     fun_name().await?
3958 }
3959
3960 async fn $0fun_name() -> _ {
3961     async {}.await;
3962     Err(())?
3963 }
3964 "#,
3965         );
3966     }
3967
3968     #[test]
3969     fn extract_with_await_and_result_producing_match_expr() {
3970         check_assist(
3971             extract_function,
3972             r#"
3973 async fn foo() -> i32 {
3974     loop {
3975         let n = 1;$0
3976         let k = async { 1 }.await;
3977         if k == 42 {
3978             break 3;
3979         }
3980         let m = k + 1;$0
3981         let h = 1 + m;
3982     }
3983 }
3984 "#,
3985             r#"
3986 async fn foo() -> i32 {
3987     loop {
3988         let n = 1;
3989         let m = match fun_name().await {
3990             Ok(value) => value,
3991             Err(value) => break value,
3992         };
3993         let h = 1 + m;
3994     }
3995 }
3996
3997 async fn $0fun_name() -> Result<i32, i32> {
3998     let k = async { 1 }.await;
3999     if k == 42 {
4000         return Err(3);
4001     }
4002     let m = k + 1;
4003     Ok(m)
4004 }
4005 "#,
4006         );
4007     }
4008
4009     #[test]
4010     fn extract_with_await_in_args() {
4011         check_assist(
4012             extract_function,
4013             r#"
4014 fn main() {
4015     $0function_call("a", some_function().await);$0
4016 }
4017
4018 async fn some_function() {
4019
4020 }
4021 "#,
4022             r#"
4023 fn main() {
4024     fun_name().await;
4025 }
4026
4027 async fn $0fun_name() {
4028     function_call("a", some_function().await);
4029 }
4030
4031 async fn some_function() {
4032
4033 }
4034 "#,
4035         );
4036     }
4037
4038     #[test]
4039     fn extract_does_not_extract_standalone_blocks() {
4040         check_assist_not_applicable(
4041             extract_function,
4042             r#"
4043 fn main() $0{}$0
4044 "#,
4045         );
4046     }
4047
4048     #[test]
4049     fn extract_adds_comma_for_match_arm() {
4050         check_assist(
4051             extract_function,
4052             r#"
4053 fn main() {
4054     match 6 {
4055         100 => $0{ 100 }$0
4056         _ => 0,
4057     }
4058 }
4059 "#,
4060             r#"
4061 fn main() {
4062     match 6 {
4063         100 => fun_name(),
4064         _ => 0,
4065     }
4066 }
4067
4068 fn $0fun_name() -> i32 {
4069     100
4070 }
4071 "#,
4072         );
4073         check_assist(
4074             extract_function,
4075             r#"
4076 fn main() {
4077     match 6 {
4078         100 => $0{ 100 }$0,
4079         _ => 0,
4080     }
4081 }
4082 "#,
4083             r#"
4084 fn main() {
4085     match 6 {
4086         100 => fun_name(),
4087         _ => 0,
4088     }
4089 }
4090
4091 fn $0fun_name() -> i32 {
4092     100
4093 }
4094 "#,
4095         );
4096     }
4097
4098     #[test]
4099     fn extract_does_not_tear_comments_apart() {
4100         check_assist(
4101             extract_function,
4102             r#"
4103 fn foo() {
4104     /*$0*/
4105     foo();
4106     foo();
4107     /*$0*/
4108 }
4109 "#,
4110             r#"
4111 fn foo() {
4112     fun_name();
4113 }
4114
4115 fn $0fun_name() {
4116     /**/
4117     foo();
4118     foo();
4119     /**/
4120 }
4121 "#,
4122         );
4123     }
4124
4125     #[test]
4126     fn extract_does_not_tear_body_apart() {
4127         check_assist(
4128             extract_function,
4129             r#"
4130 fn foo() {
4131     $0foo();
4132 }$0
4133 "#,
4134             r#"
4135 fn foo() {
4136     fun_name();
4137 }
4138
4139 fn $0fun_name() {
4140     foo();
4141 }
4142 "#,
4143         );
4144     }
4145
4146     #[test]
4147     fn extract_does_not_wrap_res_in_res() {
4148         check_assist(
4149             extract_function,
4150             r#"
4151 //- minicore: result
4152 fn foo() -> Result<(), i64> {
4153     $0Result::<i32, i64>::Ok(0)?;
4154     Ok(())$0
4155 }
4156 "#,
4157             r#"
4158 fn foo() -> Result<(), i64> {
4159     fun_name()?
4160 }
4161
4162 fn $0fun_name() -> Result<(), i64> {
4163     Result::<i32, i64>::Ok(0)?;
4164     Ok(())
4165 }
4166 "#,
4167         );
4168     }
4169
4170     #[test]
4171     fn extract_knows_const() {
4172         check_assist(
4173             extract_function,
4174             r#"
4175 const fn foo() {
4176     $0()$0
4177 }
4178 "#,
4179             r#"
4180 const fn foo() {
4181     fun_name();
4182 }
4183
4184 const fn $0fun_name() {
4185     ()
4186 }
4187 "#,
4188         );
4189         check_assist(
4190             extract_function,
4191             r#"
4192 const FOO: () = {
4193     $0()$0
4194 };
4195 "#,
4196             r#"
4197 const FOO: () = {
4198     fun_name();
4199 };
4200
4201 const fn $0fun_name() {
4202     ()
4203 }
4204 "#,
4205         );
4206     }
4207
4208     #[test]
4209     fn extract_does_not_move_outer_loop_vars() {
4210         check_assist(
4211             extract_function,
4212             r#"
4213 fn foo() {
4214     let mut x = 5;
4215     for _ in 0..10 {
4216         $0x += 1;$0
4217     }
4218 }
4219 "#,
4220             r#"
4221 fn foo() {
4222     let mut x = 5;
4223     for _ in 0..10 {
4224         fun_name(&mut x);
4225     }
4226 }
4227
4228 fn $0fun_name(x: &mut i32) {
4229     *x += 1;
4230 }
4231 "#,
4232         );
4233         check_assist(
4234             extract_function,
4235             r#"
4236 fn foo() {
4237     for _ in 0..10 {
4238         let mut x = 5;
4239         $0x += 1;$0
4240     }
4241 }
4242 "#,
4243             r#"
4244 fn foo() {
4245     for _ in 0..10 {
4246         let mut x = 5;
4247         fun_name(x);
4248     }
4249 }
4250
4251 fn $0fun_name(mut x: i32) {
4252     x += 1;
4253 }
4254 "#,
4255         );
4256         check_assist(
4257             extract_function,
4258             r#"
4259 fn foo() {
4260     loop {
4261         let mut x = 5;
4262         for _ in 0..10 {
4263             $0x += 1;$0
4264         }
4265     }
4266 }
4267 "#,
4268             r#"
4269 fn foo() {
4270     loop {
4271         let mut x = 5;
4272         for _ in 0..10 {
4273             fun_name(&mut x);
4274         }
4275     }
4276 }
4277
4278 fn $0fun_name(x: &mut i32) {
4279     *x += 1;
4280 }
4281 "#,
4282         );
4283     }
4284
4285     // regression test for #9822
4286     #[test]
4287     fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4288         check_assist(
4289             extract_function,
4290             r#"
4291 struct Foo;
4292 impl Foo {
4293     fn foo(&mut self) {}
4294 }
4295 fn foo() {
4296     let mut x = Foo;
4297     while false {
4298         let y = &mut x;
4299         $0y.foo();$0
4300     }
4301     let z = x;
4302 }
4303 "#,
4304             r#"
4305 struct Foo;
4306 impl Foo {
4307     fn foo(&mut self) {}
4308 }
4309 fn foo() {
4310     let mut x = Foo;
4311     while false {
4312         let y = &mut x;
4313         fun_name(y);
4314     }
4315     let z = x;
4316 }
4317
4318 fn $0fun_name(y: &mut Foo) {
4319     y.foo();
4320 }
4321 "#,
4322         );
4323     }
4324
4325     #[test]
4326     fn extract_with_macro_arg() {
4327         check_assist(
4328             extract_function,
4329             r#"
4330 macro_rules! m {
4331     ($val:expr) => { $val };
4332 }
4333 fn main() {
4334     let bar = "bar";
4335     $0m!(bar);$0
4336 }
4337 "#,
4338             r#"
4339 macro_rules! m {
4340     ($val:expr) => { $val };
4341 }
4342 fn main() {
4343     let bar = "bar";
4344     fun_name(bar);
4345 }
4346
4347 fn $0fun_name(bar: &str) {
4348     m!(bar);
4349 }
4350 "#,
4351         );
4352     }
4353
4354     #[test]
4355     fn unresolveable_types_default_to_placeholder() {
4356         check_assist(
4357             extract_function,
4358             r#"
4359 fn foo() {
4360     let a = __unresolved;
4361     let _ = $0{a}$0;
4362 }
4363 "#,
4364             r#"
4365 fn foo() {
4366     let a = __unresolved;
4367     let _ = fun_name(a);
4368 }
4369
4370 fn $0fun_name(a: _) -> _ {
4371     a
4372 }
4373 "#,
4374         );
4375     }
4376
4377     #[test]
4378     fn reference_mutable_param_with_further_usages() {
4379         check_assist(
4380             extract_function,
4381             r#"
4382 pub struct Foo {
4383     field: u32,
4384 }
4385
4386 pub fn testfn(arg: &mut Foo) {
4387     $0arg.field = 8;$0
4388     // Simulating access after the extracted portion
4389     arg.field = 16;
4390 }
4391 "#,
4392             r#"
4393 pub struct Foo {
4394     field: u32,
4395 }
4396
4397 pub fn testfn(arg: &mut Foo) {
4398     fun_name(arg);
4399     // Simulating access after the extracted portion
4400     arg.field = 16;
4401 }
4402
4403 fn $0fun_name(arg: &mut Foo) {
4404     arg.field = 8;
4405 }
4406 "#,
4407         );
4408     }
4409
4410     #[test]
4411     fn reference_mutable_param_without_further_usages() {
4412         check_assist(
4413             extract_function,
4414             r#"
4415 pub struct Foo {
4416     field: u32,
4417 }
4418
4419 pub fn testfn(arg: &mut Foo) {
4420     $0arg.field = 8;$0
4421 }
4422 "#,
4423             r#"
4424 pub struct Foo {
4425     field: u32,
4426 }
4427
4428 pub fn testfn(arg: &mut Foo) {
4429     fun_name(arg);
4430 }
4431
4432 fn $0fun_name(arg: &mut Foo) {
4433     arg.field = 8;
4434 }
4435 "#,
4436         );
4437     }
4438
4439     #[test]
4440     fn extract_function_copies_comment_at_start() {
4441         check_assist(
4442             extract_function,
4443             r#"
4444 fn func() {
4445     let i = 0;
4446     $0// comment here!
4447     let x = 0;$0
4448 }
4449 "#,
4450             r#"
4451 fn func() {
4452     let i = 0;
4453     fun_name();
4454 }
4455
4456 fn $0fun_name() {
4457     // comment here!
4458     let x = 0;
4459 }
4460 "#,
4461         );
4462     }
4463
4464     #[test]
4465     fn extract_function_copies_comment_in_between() {
4466         check_assist(
4467             extract_function,
4468             r#"
4469 fn func() {
4470     let i = 0;$0
4471     let a = 0;
4472     // comment here!
4473     let x = 0;$0
4474 }
4475 "#,
4476             r#"
4477 fn func() {
4478     let i = 0;
4479     fun_name();
4480 }
4481
4482 fn $0fun_name() {
4483     let a = 0;
4484     // comment here!
4485     let x = 0;
4486 }
4487 "#,
4488         );
4489     }
4490
4491     #[test]
4492     fn extract_function_copies_comment_at_end() {
4493         check_assist(
4494             extract_function,
4495             r#"
4496 fn func() {
4497     let i = 0;
4498     $0let x = 0;
4499     // comment here!$0
4500 }
4501 "#,
4502             r#"
4503 fn func() {
4504     let i = 0;
4505     fun_name();
4506 }
4507
4508 fn $0fun_name() {
4509     let x = 0;
4510     // comment here!
4511 }
4512 "#,
4513         );
4514     }
4515
4516     #[test]
4517     fn extract_function_copies_comment_indented() {
4518         check_assist(
4519             extract_function,
4520             r#"
4521 fn func() {
4522     let i = 0;
4523     $0let x = 0;
4524     while(true) {
4525         // comment here!
4526     }$0
4527 }
4528 "#,
4529             r#"
4530 fn func() {
4531     let i = 0;
4532     fun_name();
4533 }
4534
4535 fn $0fun_name() {
4536     let x = 0;
4537     while(true) {
4538         // comment here!
4539     }
4540 }
4541 "#,
4542         );
4543     }
4544
4545     // FIXME: we do want to preserve whitespace
4546     #[test]
4547     fn extract_function_does_not_preserve_whitespace() {
4548         check_assist(
4549             extract_function,
4550             r#"
4551 fn func() {
4552     let i = 0;
4553     $0let a = 0;
4554
4555     let x = 0;$0
4556 }
4557 "#,
4558             r#"
4559 fn func() {
4560     let i = 0;
4561     fun_name();
4562 }
4563
4564 fn $0fun_name() {
4565     let a = 0;
4566     let x = 0;
4567 }
4568 "#,
4569         );
4570     }
4571
4572     #[test]
4573     fn extract_function_long_form_comment() {
4574         check_assist(
4575             extract_function,
4576             r#"
4577 fn func() {
4578     let i = 0;
4579     $0/* a comment */
4580     let x = 0;$0
4581 }
4582 "#,
4583             r#"
4584 fn func() {
4585     let i = 0;
4586     fun_name();
4587 }
4588
4589 fn $0fun_name() {
4590     /* a comment */
4591     let x = 0;
4592 }
4593 "#,
4594         );
4595     }
4596 }