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