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