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