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