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