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