ide_assists/handlers/
extract_function.rs

1use std::{iter, ops::RangeInclusive};
2
3use ast::make;
4use either::Either;
5use hir::{
6    HasSource, HirDisplay, InFile, Local, LocalSource, ModuleDef, PathResolution, Semantics,
7    TypeInfo, TypeParam,
8};
9use ide_db::{
10    FxIndexSet, RootDatabase,
11    assists::GroupLabel,
12    defs::Definition,
13    famous_defs::FamousDefs,
14    helpers::mod_path_to_ast,
15    imports::insert_use::{ImportScope, insert_use},
16    search::{FileReference, ReferenceCategory, SearchScope},
17    source_change::SourceChangeBuilder,
18    syntax_helpers::node_ext::{
19        for_each_tail_expr, preorder_expr, walk_pat, walk_patterns_in_expr,
20    },
21};
22use itertools::Itertools;
23use syntax::{
24    Edition, SyntaxElement,
25    SyntaxKind::{self, COMMENT},
26    SyntaxNode, SyntaxToken, T, TextRange, TextSize, TokenAtOffset, WalkEvent,
27    ast::{
28        self, AstNode, AstToken, HasGenericParams, HasName, edit::IndentLevel,
29        edit_in_place::Indent,
30    },
31    match_ast, ted,
32};
33
34use crate::{
35    AssistId,
36    assist_context::{AssistContext, Assists, TreeMutator},
37    utils::generate_impl,
38};
39
40// Assist: extract_function
41//
42// Extracts selected statements and comments into new function.
43//
44// ```
45// fn main() {
46//     let n = 1;
47//     $0let m = n + 2;
48//     // calculate
49//     let k = m + n;$0
50//     let g = 3;
51// }
52// ```
53// ->
54// ```
55// fn main() {
56//     let n = 1;
57//     fun_name(n);
58//     let g = 3;
59// }
60//
61// fn $0fun_name(n: i32) {
62//     let m = n + 2;
63//     // calculate
64//     let k = m + n;
65// }
66// ```
67pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
68    let range = ctx.selection_trimmed();
69    if range.is_empty() {
70        return None;
71    }
72
73    let node = ctx.covering_element();
74    if matches!(node.kind(), T!['{'] | T!['}'] | T!['('] | T![')'] | T!['['] | T![']']) {
75        cov_mark::hit!(extract_function_in_braces_is_not_applicable);
76        return None;
77    }
78
79    if node.kind() == COMMENT {
80        cov_mark::hit!(extract_function_in_comment_is_not_applicable);
81        return None;
82    }
83
84    let node = match node {
85        syntax::NodeOrToken::Node(n) => n,
86        syntax::NodeOrToken::Token(t) => t.parent()?,
87    };
88
89    let body = extraction_target(&node, range)?;
90
91    let (locals_used, self_param) = body.analyze(&ctx.sema);
92
93    let anchor = if self_param.is_some() { Anchor::Method } else { Anchor::Freestanding };
94    let insert_after = node_to_insert_after(&body, anchor)?;
95    let semantics_scope = ctx.sema.scope(&insert_after)?;
96    let module = semantics_scope.module();
97    let edition = semantics_scope.krate().edition(ctx.db());
98
99    let (container_info, contains_tail_expr) = body.analyze_container(&ctx.sema, edition)?;
100
101    let ret_ty = body.return_ty(ctx)?;
102    let control_flow = body.external_control_flow(ctx, &container_info)?;
103    let ret_values = body.ret_values(ctx, node.parent().as_ref().unwrap_or(&node));
104
105    let target_range = body.text_range();
106
107    let scope = ImportScope::find_insert_use_container(&node, &ctx.sema)?;
108
109    acc.add_group(
110        &GroupLabel("Extract into...".to_owned()),
111        AssistId::refactor_extract("extract_function"),
112        "Extract into function",
113        target_range,
114        move |builder| {
115            let outliving_locals: Vec<_> = ret_values.collect();
116            if stdx::never!(!outliving_locals.is_empty() && !ret_ty.is_unit()) {
117                // We should not have variables that outlive body if we have expression block
118                return;
119            }
120
121            let params = body.extracted_function_params(ctx, &container_info, locals_used);
122
123            let name = make_function_name(&semantics_scope);
124
125            let fun = Function {
126                name,
127                self_param,
128                params,
129                control_flow,
130                ret_ty,
131                body,
132                outliving_locals,
133                contains_tail_expr,
134                mods: container_info,
135            };
136
137            let new_indent = IndentLevel::from_node(&insert_after);
138            let old_indent = fun.body.indent_level();
139
140            let insert_after = builder.make_syntax_mut(insert_after);
141
142            let call_expr = make_call(ctx, &fun, old_indent);
143
144            // Map the element range to replace into the mutable version
145            let elements = match &fun.body {
146                FunctionBody::Expr(expr) => {
147                    // expr itself becomes the replacement target
148                    let expr = &builder.make_mut(expr.clone());
149                    let node = SyntaxElement::Node(expr.syntax().clone());
150
151                    node.clone()..=node
152                }
153                FunctionBody::Span { parent, elements, .. } => {
154                    // Map the element range into the mutable versions
155                    let parent = builder.make_mut(parent.clone());
156
157                    let start = parent
158                        .syntax()
159                        .children_with_tokens()
160                        .nth(elements.start().index())
161                        .expect("should be able to find mutable start element");
162
163                    let end = parent
164                        .syntax()
165                        .children_with_tokens()
166                        .nth(elements.end().index())
167                        .expect("should be able to find mutable end element");
168
169                    start..=end
170                }
171            };
172
173            let has_impl_wrapper =
174                insert_after.ancestors().any(|a| a.kind() == SyntaxKind::IMPL && a != insert_after);
175
176            let fn_def = format_function(ctx, module, &fun, old_indent).clone_for_update();
177
178            if let Some(cap) = ctx.config.snippet_cap
179                && let Some(name) = fn_def.name()
180            {
181                builder.add_tabstop_before(cap, name);
182            }
183
184            let fn_def = match fun.self_param_adt(ctx) {
185                Some(adt) if anchor == Anchor::Method && !has_impl_wrapper => {
186                    fn_def.indent(1.into());
187
188                    let impl_ = generate_impl(&adt);
189                    impl_.indent(new_indent);
190                    impl_.get_or_create_assoc_item_list().add_item(fn_def.into());
191
192                    impl_.syntax().clone()
193                }
194                _ => {
195                    fn_def.indent(new_indent);
196
197                    fn_def.syntax().clone()
198                }
199            };
200
201            // There are external control flows
202            if fun
203                .control_flow
204                .kind
205                .is_some_and(|kind| matches!(kind, FlowKind::Break(_, _) | FlowKind::Continue(_)))
206            {
207                let scope = builder.make_import_scope_mut(scope);
208                let control_flow_enum =
209                    FamousDefs(&ctx.sema, module.krate(ctx.db())).core_ops_ControlFlow();
210
211                if let Some(control_flow_enum) = control_flow_enum {
212                    let cfg =
213                        ctx.config.find_path_config(ctx.sema.is_nightly(module.krate(ctx.sema.db)));
214                    let mod_path = module.find_use_path(
215                        ctx.sema.db,
216                        ModuleDef::from(control_flow_enum),
217                        ctx.config.insert_use.prefix_kind,
218                        cfg,
219                    );
220
221                    if let Some(mod_path) = mod_path {
222                        insert_use(
223                            &scope,
224                            mod_path_to_ast(&mod_path, edition),
225                            &ctx.config.insert_use,
226                        );
227                    }
228                }
229            }
230
231            // Replace the call site with the call to the new function
232            fixup_call_site(builder, &fun.body);
233            ted::replace_all(elements, vec![call_expr.into()]);
234
235            // Insert the newly extracted function (or impl)
236            ted::insert_all_raw(
237                ted::Position::after(insert_after),
238                vec![make::tokens::whitespace(&format!("\n\n{new_indent}")).into(), fn_def.into()],
239            );
240        },
241    )
242}
243
244fn make_function_name(semantics_scope: &hir::SemanticsScope<'_>) -> ast::NameRef {
245    let mut names_in_scope = vec![];
246    semantics_scope.process_all_names(&mut |name, _| {
247        names_in_scope.push(
248            name.display(semantics_scope.db, semantics_scope.krate().edition(semantics_scope.db))
249                .to_string(),
250        )
251    });
252
253    let default_name = "fun_name";
254
255    let mut name = default_name.to_owned();
256    let mut counter = 0;
257    while names_in_scope.contains(&name) {
258        counter += 1;
259        name = format!("{default_name}{counter}")
260    }
261    make::name_ref(&name)
262}
263
264/// Try to guess what user wants to extract
265///
266/// We have basically have two cases:
267/// * We want whole node, like `loop {}`, `2 + 2`, `{ let n = 1; }` exprs.
268///   Then we can use `ast::Expr`
269/// * We want a few statements for a block. E.g.
270///   ```ignore
271///   fn foo() -> i32 {
272///     let m = 1;
273///     $0
274///     let n = 2;
275///     let k = 3;
276///     k + n
277///     $0
278///   }
279///   ```
280///
281fn extraction_target(node: &SyntaxNode, selection_range: TextRange) -> Option<FunctionBody> {
282    if let Some(stmt) = ast::Stmt::cast(node.clone()) {
283        return match stmt {
284            ast::Stmt::Item(_) => None,
285            ast::Stmt::ExprStmt(_) | ast::Stmt::LetStmt(_) => FunctionBody::from_range(
286                node.parent().and_then(ast::StmtList::cast)?,
287                node.text_range(),
288            ),
289        };
290    }
291
292    // Covering element returned the parent block of one or multiple statements that have been selected
293    if let Some(stmt_list) = ast::StmtList::cast(node.clone()) {
294        if let Some(block_expr) = stmt_list.syntax().parent().and_then(ast::BlockExpr::cast)
295            && block_expr.syntax().text_range() == selection_range
296        {
297            return FunctionBody::from_expr(block_expr.into());
298        }
299
300        // Extract the full statements.
301        return FunctionBody::from_range(stmt_list, selection_range);
302    }
303
304    let expr = ast::Expr::cast(node.clone())?;
305    // A node got selected fully
306    if node.text_range() == selection_range {
307        return FunctionBody::from_expr(expr);
308    }
309
310    node.ancestors().find_map(ast::Expr::cast).and_then(FunctionBody::from_expr)
311}
312
313#[derive(Debug)]
314struct Function<'db> {
315    name: ast::NameRef,
316    self_param: Option<ast::SelfParam>,
317    params: Vec<Param<'db>>,
318    control_flow: ControlFlow<'db>,
319    ret_ty: RetType<'db>,
320    body: FunctionBody,
321    outliving_locals: Vec<OutlivedLocal>,
322    /// Whether at least one of the container's tail expr is contained in the range we're extracting.
323    contains_tail_expr: bool,
324    mods: ContainerInfo<'db>,
325}
326
327#[derive(Debug)]
328struct Param<'db> {
329    var: Local,
330    ty: hir::Type<'db>,
331    move_local: bool,
332    requires_mut: bool,
333    is_copy: bool,
334}
335
336#[derive(Debug, Clone, Copy, PartialEq, Eq)]
337enum ParamKind {
338    Value,
339    MutValue,
340    SharedRef,
341    MutRef,
342}
343
344#[derive(Debug)]
345enum FunType<'db> {
346    Unit,
347    Single(hir::Type<'db>),
348    Tuple(Vec<hir::Type<'db>>),
349}
350
351/// Where to put extracted function definition
352#[derive(Debug, Eq, PartialEq, Clone, Copy)]
353enum Anchor {
354    /// Extract free function and put right after current top-level function
355    Freestanding,
356    /// Extract method and put right after current function in the impl-block
357    Method,
358}
359
360// FIXME: ControlFlow and ContainerInfo both track some function modifiers, feels like these two should
361// probably be merged somehow.
362#[derive(Debug)]
363struct ControlFlow<'db> {
364    kind: Option<FlowKind<'db>>,
365    is_async: bool,
366    is_unsafe: bool,
367}
368
369/// The thing whose expression we are extracting from. Can be a function, const, static, const arg, ...
370#[derive(Clone, Debug)]
371struct ContainerInfo<'db> {
372    is_const: bool,
373    parent_loop: Option<SyntaxNode>,
374    /// The function's return type, const's type etc.
375    ret_type: Option<hir::Type<'db>>,
376    generic_param_lists: Vec<ast::GenericParamList>,
377    where_clauses: Vec<ast::WhereClause>,
378    edition: Edition,
379}
380
381/// Control flow that is exported from extracted function
382///
383/// E.g.:
384/// ```ignore
385/// loop {
386///     $0
387///     if 42 == 42 {
388///         break;
389///     }
390///     $0
391/// }
392/// ```
393#[derive(Debug, Clone)]
394enum FlowKind<'db> {
395    /// Return with value (`return $expr;`)
396    Return(Option<ast::Expr>),
397    Try {
398        kind: TryKind<'db>,
399    },
400    /// Break with label and value (`break 'label $expr;`)
401    Break(Option<ast::Lifetime>, Option<ast::Expr>),
402    /// Continue with label (`continue 'label;`)
403    Continue(Option<ast::Lifetime>),
404}
405
406#[derive(Debug, Clone)]
407enum TryKind<'db> {
408    Option,
409    Result { ty: hir::Type<'db> },
410}
411
412#[derive(Debug)]
413enum RetType<'db> {
414    Expr(hir::Type<'db>),
415    Stmt,
416}
417
418impl RetType<'_> {
419    fn is_unit(&self) -> bool {
420        match self {
421            RetType::Expr(ty) => ty.is_unit(),
422            RetType::Stmt => true,
423        }
424    }
425}
426
427/// Semantically same as `ast::Expr`, but preserves identity when using only part of the Block
428/// This is the future function body, the part that is being extracted.
429#[derive(Debug)]
430enum FunctionBody {
431    Expr(ast::Expr),
432    Span { parent: ast::StmtList, elements: RangeInclusive<SyntaxElement>, text_range: TextRange },
433}
434
435#[derive(Debug)]
436struct OutlivedLocal {
437    local: Local,
438    mut_usage_outside_body: bool,
439}
440
441/// Container of local variable usages
442///
443/// Semantically same as `UsageSearchResult`, but provides more convenient interface
444struct LocalUsages(ide_db::search::UsageSearchResult);
445
446impl LocalUsages {
447    fn find_local_usages(ctx: &AssistContext<'_>, var: Local) -> Self {
448        Self(
449            Definition::Local(var)
450                .usages(&ctx.sema)
451                .in_scope(&SearchScope::single_file(ctx.file_id()))
452                .all(),
453        )
454    }
455
456    fn iter(&self) -> impl Iterator<Item = &FileReference> + '_ {
457        self.0.iter().flat_map(|(_, rs)| rs)
458    }
459}
460
461impl<'db> Function<'db> {
462    fn return_type(&self, ctx: &AssistContext<'db>) -> FunType<'db> {
463        match &self.ret_ty {
464            RetType::Expr(ty) if ty.is_unit() => FunType::Unit,
465            RetType::Expr(ty) => FunType::Single(ty.clone()),
466            RetType::Stmt => match self.outliving_locals.as_slice() {
467                [] => FunType::Unit,
468                [var] => FunType::Single(var.local.ty(ctx.db())),
469                vars => {
470                    let types = vars.iter().map(|v| v.local.ty(ctx.db())).collect();
471                    FunType::Tuple(types)
472                }
473            },
474        }
475    }
476
477    fn self_param_adt(&self, ctx: &AssistContext<'_>) -> Option<ast::Adt> {
478        let self_param = self.self_param.as_ref()?;
479        let def = ctx.sema.to_def(self_param)?;
480        let adt = def.ty(ctx.db()).strip_references().as_adt()?;
481        let InFile { file_id: _, value } = adt.source(ctx.db())?;
482        Some(value)
483    }
484}
485
486impl ParamKind {
487    fn is_ref(&self) -> bool {
488        matches!(self, ParamKind::SharedRef | ParamKind::MutRef)
489    }
490}
491
492impl<'db> Param<'db> {
493    fn kind(&self) -> ParamKind {
494        match (self.move_local, self.requires_mut, self.is_copy) {
495            (false, true, _) => ParamKind::MutRef,
496            (false, false, false) => ParamKind::SharedRef,
497            (true, true, _) => ParamKind::MutValue,
498            (_, false, _) => ParamKind::Value,
499        }
500    }
501
502    fn to_arg(&self, ctx: &AssistContext<'db>, edition: Edition) -> ast::Expr {
503        let var = path_expr_from_local(ctx, self.var, edition);
504        match self.kind() {
505            ParamKind::Value | ParamKind::MutValue => var,
506            ParamKind::SharedRef => make::expr_ref(var, false),
507            ParamKind::MutRef => make::expr_ref(var, true),
508        }
509    }
510
511    fn to_param(
512        &self,
513        ctx: &AssistContext<'_>,
514        module: hir::Module,
515        edition: Edition,
516    ) -> ast::Param {
517        let var = self.var.name(ctx.db()).display(ctx.db(), edition).to_string();
518        let var_name = make::name(&var);
519        let pat = match self.kind() {
520            ParamKind::MutValue => make::ident_pat(false, true, var_name),
521            ParamKind::Value | ParamKind::SharedRef | ParamKind::MutRef => {
522                make::ext::simple_ident_pat(var_name)
523            }
524        };
525
526        let ty = make_ty(&self.ty, ctx, module);
527        let ty = match self.kind() {
528            ParamKind::Value | ParamKind::MutValue => ty,
529            ParamKind::SharedRef => make::ty_ref(ty, false),
530            ParamKind::MutRef => make::ty_ref(ty, true),
531        };
532
533        make::param(pat.into(), ty)
534    }
535}
536
537impl<'db> TryKind<'db> {
538    fn of_ty(
539        ty: hir::Type<'db>,
540        ctx: &AssistContext<'db>,
541        edition: Edition,
542    ) -> Option<TryKind<'db>> {
543        if ty.is_unknown() {
544            // We favour Result for `expr?`
545            return Some(TryKind::Result { ty });
546        }
547        let adt = ty.as_adt()?;
548        let name = adt.name(ctx.db());
549        // FIXME: use lang items to determine if it is std type or user defined
550        //        E.g. if user happens to define type named `Option`, we would have false positive
551        let name = &name.display(ctx.db(), edition).to_string();
552        match name.as_str() {
553            "Option" => Some(TryKind::Option),
554            "Result" => Some(TryKind::Result { ty }),
555            _ => None,
556        }
557    }
558}
559
560impl<'db> FlowKind<'db> {
561    fn make_result_handler(&self, expr: Option<ast::Expr>) -> ast::Expr {
562        match self {
563            FlowKind::Return(_) => make::expr_return(expr),
564            FlowKind::Break(label, _) => make::expr_break(label.clone(), expr),
565            FlowKind::Try { .. } => {
566                stdx::never!("cannot have result handler with try");
567                expr.unwrap_or_else(|| make::expr_return(None))
568            }
569            FlowKind::Continue(label) => {
570                stdx::always!(expr.is_none(), "continue with value is not possible");
571                make::expr_continue(label.clone())
572            }
573        }
574    }
575
576    fn expr_ty(&self, ctx: &AssistContext<'db>) -> Option<hir::Type<'db>> {
577        match self {
578            FlowKind::Return(Some(expr)) | FlowKind::Break(_, Some(expr)) => {
579                ctx.sema.type_of_expr(expr).map(TypeInfo::adjusted)
580            }
581            FlowKind::Try { .. } => {
582                stdx::never!("try does not have defined expr_ty");
583                None
584            }
585            _ => None,
586        }
587    }
588}
589
590impl FunctionBody {
591    fn parent(&self) -> Option<SyntaxNode> {
592        match self {
593            FunctionBody::Expr(expr) => expr.syntax().parent(),
594            FunctionBody::Span { parent, .. } => Some(parent.syntax().clone()),
595        }
596    }
597
598    fn node(&self) -> &SyntaxNode {
599        match self {
600            FunctionBody::Expr(e) => e.syntax(),
601            FunctionBody::Span { parent, .. } => parent.syntax(),
602        }
603    }
604
605    fn extracted_from_trait_impl(&self) -> bool {
606        match self.node().ancestors().find_map(ast::Impl::cast) {
607            Some(c) => c.trait_().is_some(),
608            None => false,
609        }
610    }
611
612    fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
613        match self {
614            FunctionBody::Expr(expr) => expr.syntax().descendants(),
615            FunctionBody::Span { parent, .. } => parent.syntax().descendants(),
616        }
617    }
618
619    fn descendant_paths(&self) -> impl Iterator<Item = ast::Path> {
620        self.descendants().filter_map(|node| {
621            match_ast! {
622                match node {
623                    ast::Path(it) => Some(it),
624                    _ => None
625                }
626            }
627        })
628    }
629
630    fn from_expr(expr: ast::Expr) -> Option<Self> {
631        match expr {
632            ast::Expr::BreakExpr(it) => it.expr().map(Self::Expr),
633            ast::Expr::ReturnExpr(it) => it.expr().map(Self::Expr),
634            ast::Expr::BlockExpr(it) if !it.is_standalone() => None,
635            expr => Some(Self::Expr(expr)),
636        }
637    }
638
639    fn from_range(parent: ast::StmtList, selected: TextRange) -> Option<FunctionBody> {
640        let full_body = parent.syntax().children_with_tokens();
641
642        // Get all of the elements intersecting with the selection
643        let mut stmts_in_selection = full_body
644            .filter(|it| ast::Stmt::can_cast(it.kind()) || it.kind() == COMMENT)
645            .filter(|it| selected.intersect(it.text_range()).filter(|it| !it.is_empty()).is_some());
646
647        let first_element = stmts_in_selection.next();
648
649        // If the tail expr is part of the selection too, make that the last element
650        // Otherwise use the last stmt
651        let last_element = if let Some(tail_expr) =
652            parent.tail_expr().filter(|it| selected.intersect(it.syntax().text_range()).is_some())
653        {
654            Some(tail_expr.syntax().clone().into())
655        } else {
656            stmts_in_selection.last()
657        };
658
659        let elements = match (first_element, last_element) {
660            (None, _) => {
661                cov_mark::hit!(extract_function_empty_selection_is_not_applicable);
662                return None;
663            }
664            (Some(first), None) => first.clone()..=first,
665            (Some(first), Some(last)) => first..=last,
666        };
667
668        let text_range = elements.start().text_range().cover(elements.end().text_range());
669
670        Some(Self::Span { parent, elements, text_range })
671    }
672
673    fn indent_level(&self) -> IndentLevel {
674        match &self {
675            FunctionBody::Expr(expr) => IndentLevel::from_node(expr.syntax()),
676            FunctionBody::Span { parent, .. } => IndentLevel::from_node(parent.syntax()) + 1,
677        }
678    }
679
680    fn tail_expr(&self) -> Option<ast::Expr> {
681        match &self {
682            FunctionBody::Expr(expr) => Some(expr.clone()),
683            FunctionBody::Span { parent, text_range, .. } => {
684                let tail_expr = parent.tail_expr()?;
685                text_range.contains_range(tail_expr.syntax().text_range()).then_some(tail_expr)
686            }
687        }
688    }
689
690    fn preorder_expr(&self, cb: &mut dyn FnMut(WalkEvent<ast::Expr>) -> bool) {
691        match self {
692            FunctionBody::Expr(expr) => preorder_expr(expr, cb),
693            FunctionBody::Span { parent, text_range, .. } => {
694                parent
695                    .statements()
696                    .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
697                    .filter_map(|stmt| match stmt {
698                        ast::Stmt::ExprStmt(expr_stmt) => expr_stmt.expr().map(|e| vec![e]),
699                        ast::Stmt::Item(_) => None,
700                        ast::Stmt::LetStmt(stmt) => {
701                            let init = stmt.initializer();
702                            let let_else = stmt
703                                .let_else()
704                                .and_then(|le| le.block_expr())
705                                .map(ast::Expr::BlockExpr);
706
707                            match (init, let_else) {
708                                (Some(i), Some(le)) => Some(vec![i, le]),
709                                (Some(i), _) => Some(vec![i]),
710                                (_, Some(le)) => Some(vec![le]),
711                                _ => None,
712                            }
713                        }
714                    })
715                    .flatten()
716                    .for_each(|expr| preorder_expr(&expr, cb));
717                if let Some(expr) = parent
718                    .tail_expr()
719                    .filter(|it| text_range.contains_range(it.syntax().text_range()))
720                {
721                    preorder_expr(&expr, cb);
722                }
723            }
724        }
725    }
726
727    fn walk_pat(&self, cb: &mut dyn FnMut(ast::Pat)) {
728        match self {
729            FunctionBody::Expr(expr) => walk_patterns_in_expr(expr, cb),
730            FunctionBody::Span { parent, text_range, .. } => {
731                parent
732                    .statements()
733                    .filter(|stmt| text_range.contains_range(stmt.syntax().text_range()))
734                    .for_each(|stmt| match stmt {
735                        ast::Stmt::ExprStmt(expr_stmt) => {
736                            if let Some(expr) = expr_stmt.expr() {
737                                walk_patterns_in_expr(&expr, cb)
738                            }
739                        }
740                        ast::Stmt::Item(_) => (),
741                        ast::Stmt::LetStmt(stmt) => {
742                            if let Some(pat) = stmt.pat() {
743                                _ = walk_pat(&pat, &mut |pat| {
744                                    cb(pat);
745                                    std::ops::ControlFlow::<(), ()>::Continue(())
746                                });
747                            }
748                            if let Some(expr) = stmt.initializer() {
749                                walk_patterns_in_expr(&expr, cb);
750                            }
751                        }
752                    });
753                if let Some(expr) = parent
754                    .tail_expr()
755                    .filter(|it| text_range.contains_range(it.syntax().text_range()))
756                {
757                    walk_patterns_in_expr(&expr, cb);
758                }
759            }
760        }
761    }
762
763    fn text_range(&self) -> TextRange {
764        match self {
765            FunctionBody::Expr(expr) => expr.syntax().text_range(),
766            &FunctionBody::Span { text_range, .. } => text_range,
767        }
768    }
769
770    fn contains_range(&self, range: TextRange) -> bool {
771        self.text_range().contains_range(range)
772    }
773
774    fn precedes_range(&self, range: TextRange) -> bool {
775        self.text_range().end() <= range.start()
776    }
777
778    fn contains_node(&self, node: &SyntaxNode) -> bool {
779        self.contains_range(node.text_range())
780    }
781}
782
783impl FunctionBody {
784    /// Analyzes a function body, returning the used local variables that are referenced in it as well as
785    /// whether it contains an await expression.
786    fn analyze(
787        &self,
788        sema: &Semantics<'_, RootDatabase>,
789    ) -> (FxIndexSet<Local>, Option<ast::SelfParam>) {
790        let mut self_param = None;
791        let mut res = FxIndexSet::default();
792
793        let (text_range, element) = match self {
794            FunctionBody::Expr(expr) => (expr.syntax().text_range(), Either::Left(expr)),
795            FunctionBody::Span { parent, text_range, .. } => (*text_range, Either::Right(parent)),
796        };
797
798        let mut add_name_if_local = |local_ref: Local| {
799            // locals defined inside macros are not relevant to us
800            let InFile { file_id, value } = local_ref.primary_source(sema.db).source;
801            if !file_id.is_macro() {
802                match value {
803                    Either::Right(it) => {
804                        self_param.replace(it);
805                    }
806                    Either::Left(_) => {
807                        res.insert(local_ref);
808                    }
809                }
810            }
811        };
812
813        if let Some(locals) = sema.locals_used(element, text_range) {
814            locals.into_iter().for_each(&mut add_name_if_local);
815        }
816
817        (res, self_param)
818    }
819
820    fn analyze_container<'db>(
821        &self,
822        sema: &Semantics<'db, RootDatabase>,
823        edition: Edition,
824    ) -> Option<(ContainerInfo<'db>, bool)> {
825        let mut ancestors = self.parent()?.ancestors();
826        let infer_expr_opt = |expr| sema.type_of_expr(&expr?).map(TypeInfo::adjusted);
827        let mut parent_loop = None;
828        let mut set_parent_loop = |loop_: &dyn ast::HasLoopBody| {
829            if loop_
830                .loop_body()
831                .is_some_and(|it| it.syntax().text_range().contains_range(self.text_range()))
832            {
833                parent_loop.get_or_insert(loop_.syntax().clone());
834            }
835        };
836
837        let (is_const, expr, ty) = loop {
838            let anc = ancestors.next()?;
839            break match_ast! {
840                match anc {
841                    ast::ClosureExpr(closure) => (false, closure.body(), infer_expr_opt(closure.body())),
842                    ast::BlockExpr(block_expr) => {
843                        let (constness, block) = match block_expr.modifier() {
844                            Some(ast::BlockModifier::Const(_)) => (true, block_expr),
845                            Some(ast::BlockModifier::Try(_)) => (false, block_expr),
846                            Some(ast::BlockModifier::Label(label)) if label.lifetime().is_some() => (false, block_expr),
847                            _ => continue,
848                        };
849                        let expr = Some(ast::Expr::BlockExpr(block));
850                        (constness, expr.clone(), infer_expr_opt(expr))
851                    },
852                    ast::Fn(fn_) => {
853                        let func = sema.to_def(&fn_)?;
854                        let mut ret_ty = func.ret_type(sema.db);
855                        if func.is_async(sema.db)
856                            && let Some(async_ret) = func.async_ret_type(sema.db) {
857                                ret_ty = async_ret;
858                            }
859                        (fn_.const_token().is_some(), fn_.body().map(ast::Expr::BlockExpr), Some(ret_ty))
860                    },
861                    ast::Static(statik) => {
862                        (true, statik.body(), Some(sema.to_def(&statik)?.ty(sema.db)))
863                    },
864                    ast::ConstArg(ca) => {
865                        (true, ca.expr(), infer_expr_opt(ca.expr()))
866                    },
867                    ast::Const(konst) => {
868                        (true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db)))
869                    },
870                    ast::ConstParam(cp) => {
871                        (true, cp.default_val()?.expr(), Some(sema.to_def(&cp)?.ty(sema.db)))
872                    },
873                    ast::ConstBlockPat(cbp) => {
874                        let expr = cbp.block_expr().map(ast::Expr::BlockExpr);
875                        (true, expr.clone(), infer_expr_opt(expr))
876                    },
877                    ast::Variant(__) => return None,
878                    ast::Meta(__) => return None,
879                    ast::LoopExpr(it) => {
880                        set_parent_loop(&it);
881                        continue;
882                    },
883                    ast::ForExpr(it) => {
884                        set_parent_loop(&it);
885                        continue;
886                    },
887                    ast::WhileExpr(it) => {
888                        set_parent_loop(&it);
889                        continue;
890                    },
891                    _ => continue,
892                }
893            };
894        };
895
896        let expr = expr?;
897        let contains_tail_expr = if let Some(body_tail) = self.tail_expr() {
898            let mut contains_tail_expr = false;
899            let tail_expr_range = body_tail.syntax().text_range();
900            for_each_tail_expr(&expr, &mut |e| {
901                if tail_expr_range.contains_range(e.syntax().text_range()) {
902                    contains_tail_expr = true;
903                }
904            });
905            contains_tail_expr
906        } else {
907            false
908        };
909
910        let parent = self.parent()?;
911        let parents = generic_parents(&parent);
912        let generic_param_lists = parents.iter().filter_map(|it| it.generic_param_list()).collect();
913        let where_clauses = parents.iter().filter_map(|it| it.where_clause()).collect();
914
915        Some((
916            ContainerInfo {
917                is_const,
918                parent_loop,
919                ret_type: ty,
920                generic_param_lists,
921                where_clauses,
922                edition,
923            },
924            contains_tail_expr,
925        ))
926    }
927
928    fn return_ty<'db>(&self, ctx: &AssistContext<'db>) -> Option<RetType<'db>> {
929        match self.tail_expr() {
930            Some(expr) => ctx.sema.type_of_expr(&expr).map(TypeInfo::original).map(RetType::Expr),
931            None => Some(RetType::Stmt),
932        }
933    }
934
935    /// Local variables defined inside `body` that are accessed outside of it
936    fn ret_values<'a>(
937        &self,
938        ctx: &'a AssistContext<'_>,
939        parent: &SyntaxNode,
940    ) -> impl Iterator<Item = OutlivedLocal> + 'a {
941        let parent = parent.clone();
942        let range = self.text_range();
943        locals_defined_in_body(&ctx.sema, self)
944            .into_iter()
945            .filter_map(move |local| local_outlives_body(ctx, range, local, &parent))
946    }
947
948    /// Analyses the function body for external control flow.
949    fn external_control_flow<'db>(
950        &self,
951        ctx: &AssistContext<'db>,
952        container_info: &ContainerInfo<'db>,
953    ) -> Option<ControlFlow<'db>> {
954        let mut ret_expr = None;
955        let mut try_expr = None;
956        let mut break_expr = None;
957        let mut continue_expr = None;
958        let mut is_async = false;
959        let mut _is_unsafe = false;
960
961        let mut unsafe_depth = 0;
962        let mut loop_depth = 0;
963
964        self.preorder_expr(&mut |expr| {
965            let expr = match expr {
966                WalkEvent::Enter(e) => e,
967                WalkEvent::Leave(expr) => {
968                    match expr {
969                        ast::Expr::LoopExpr(_)
970                        | ast::Expr::ForExpr(_)
971                        | ast::Expr::WhileExpr(_) => loop_depth -= 1,
972                        ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
973                            unsafe_depth -= 1
974                        }
975                        _ => (),
976                    }
977                    return false;
978                }
979            };
980            match expr {
981                ast::Expr::LoopExpr(_) | ast::Expr::ForExpr(_) | ast::Expr::WhileExpr(_) => {
982                    loop_depth += 1;
983                }
984                ast::Expr::BlockExpr(block_expr) if block_expr.unsafe_token().is_some() => {
985                    unsafe_depth += 1
986                }
987                ast::Expr::ReturnExpr(it) => {
988                    ret_expr = Some(it);
989                }
990                ast::Expr::TryExpr(it) => {
991                    try_expr = Some(it);
992                }
993                ast::Expr::BreakExpr(it) if loop_depth == 0 => {
994                    break_expr = Some(it);
995                }
996                ast::Expr::ContinueExpr(it) if loop_depth == 0 => {
997                    continue_expr = Some(it);
998                }
999                ast::Expr::AwaitExpr(_) => is_async = true,
1000                // FIXME: Do unsafe analysis on expression, sem highlighting knows this so we should be able
1001                // to just lift that out of there
1002                // expr if unsafe_depth ==0 && expr.is_unsafe => is_unsafe = true,
1003                _ => {}
1004            }
1005            false
1006        });
1007
1008        let kind = match (try_expr, ret_expr, break_expr, continue_expr) {
1009            (Some(_), _, None, None) => {
1010                let ret_ty = container_info.ret_type.clone()?;
1011                let kind = TryKind::of_ty(ret_ty, ctx, container_info.edition)?;
1012
1013                Some(FlowKind::Try { kind })
1014            }
1015            (Some(_), _, _, _) => {
1016                cov_mark::hit!(external_control_flow_try_and_bc);
1017                return None;
1018            }
1019            (None, Some(r), None, None) => Some(FlowKind::Return(r.expr())),
1020            (None, Some(_), _, _) => {
1021                cov_mark::hit!(external_control_flow_return_and_bc);
1022                return None;
1023            }
1024            (None, None, Some(_), Some(_)) => {
1025                cov_mark::hit!(external_control_flow_break_and_continue);
1026                return None;
1027            }
1028            (None, None, Some(b), None) => Some(FlowKind::Break(b.lifetime(), b.expr())),
1029            (None, None, None, Some(c)) => Some(FlowKind::Continue(c.lifetime())),
1030            (None, None, None, None) => None,
1031        };
1032
1033        Some(ControlFlow { kind, is_async, is_unsafe: _is_unsafe })
1034    }
1035
1036    /// find variables that should be extracted as params
1037    ///
1038    /// Computes additional info that affects param type and mutability
1039    fn extracted_function_params<'db>(
1040        &self,
1041        ctx: &AssistContext<'db>,
1042        container_info: &ContainerInfo<'db>,
1043        locals: FxIndexSet<Local>,
1044    ) -> Vec<Param<'db>> {
1045        locals
1046            .into_iter()
1047            .sorted()
1048            .map(|local| (local, local.primary_source(ctx.db())))
1049            .filter(|(_, src)| is_defined_outside_of_body(ctx, self, src))
1050            .filter_map(|(local, src)| match src.into_ident_pat() {
1051                Some(src) => Some((local, src)),
1052                None => {
1053                    stdx::never!(false, "Local::is_self returned false, but source is SelfParam");
1054                    None
1055                }
1056            })
1057            .map(|(var, src)| {
1058                let usages = LocalUsages::find_local_usages(ctx, var);
1059                let ty = var.ty(ctx.db());
1060
1061                let defined_outside_parent_loop = container_info
1062                    .parent_loop
1063                    .as_ref()
1064                    .is_none_or(|it| it.text_range().contains_range(src.syntax().text_range()));
1065
1066                let is_copy = ty.is_copy(ctx.db());
1067                let has_usages = self.has_usages_after_body(&usages);
1068                let requires_mut =
1069                    !ty.is_mutable_reference() && has_exclusive_usages(ctx, &usages, self);
1070                // We can move the value into the function call if it's not used after the call,
1071                // if the var is not used but defined outside a loop we are extracting from we can't move it either
1072                // as the function will reuse it in the next iteration.
1073                let move_local = (!has_usages && defined_outside_parent_loop) || ty.is_reference();
1074                Param { var, ty, move_local, requires_mut, is_copy }
1075            })
1076            .collect()
1077    }
1078
1079    fn has_usages_after_body(&self, usages: &LocalUsages) -> bool {
1080        usages.iter().any(|reference| self.precedes_range(reference.range))
1081    }
1082}
1083
1084enum GenericParent {
1085    Fn(ast::Fn),
1086    Impl(ast::Impl),
1087    Trait(ast::Trait),
1088}
1089
1090impl GenericParent {
1091    fn generic_param_list(&self) -> Option<ast::GenericParamList> {
1092        match self {
1093            GenericParent::Fn(fn_) => fn_.generic_param_list(),
1094            GenericParent::Impl(impl_) => impl_.generic_param_list(),
1095            GenericParent::Trait(trait_) => trait_.generic_param_list(),
1096        }
1097    }
1098
1099    fn where_clause(&self) -> Option<ast::WhereClause> {
1100        match self {
1101            GenericParent::Fn(fn_) => fn_.where_clause(),
1102            GenericParent::Impl(impl_) => impl_.where_clause(),
1103            GenericParent::Trait(trait_) => trait_.where_clause(),
1104        }
1105    }
1106}
1107
1108/// Search `parent`'s ancestors for items with potentially applicable generic parameters
1109fn generic_parents(parent: &SyntaxNode) -> Vec<GenericParent> {
1110    let mut list = Vec::new();
1111    if let Some(parent_item) = parent.ancestors().find_map(ast::Item::cast)
1112        && let ast::Item::Fn(ref fn_) = parent_item
1113    {
1114        if let Some(parent_parent) =
1115            parent_item.syntax().parent().and_then(|it| it.parent()).and_then(ast::Item::cast)
1116        {
1117            match parent_parent {
1118                ast::Item::Impl(impl_) => list.push(GenericParent::Impl(impl_)),
1119                ast::Item::Trait(trait_) => list.push(GenericParent::Trait(trait_)),
1120                _ => (),
1121            }
1122        }
1123        list.push(GenericParent::Fn(fn_.clone()));
1124    }
1125    list
1126}
1127
1128/// checks if relevant var is used with `&mut` access inside body
1129fn has_exclusive_usages(
1130    ctx: &AssistContext<'_>,
1131    usages: &LocalUsages,
1132    body: &FunctionBody,
1133) -> bool {
1134    usages
1135        .iter()
1136        .filter(|reference| body.contains_range(reference.range))
1137        .any(|reference| reference_is_exclusive(reference, body, ctx))
1138}
1139
1140/// checks if this reference requires `&mut` access inside node
1141fn reference_is_exclusive(
1142    reference: &FileReference,
1143    node: &dyn HasTokenAtOffset,
1144    ctx: &AssistContext<'_>,
1145) -> bool {
1146    // FIXME: this quite an incorrect way to go about doing this :-)
1147    // `FileReference` is an IDE-type --- it encapsulates data communicated to the human,
1148    // but doesn't necessary fully reflect all the intricacies of the underlying language semantics
1149    // The correct approach here would be to expose this entire analysis as a method on some hir
1150    // type. Something like `body.free_variables(statement_range)`.
1151
1152    // we directly modify variable with set: `n = 0`, `n += 1`
1153    if reference.category.contains(ReferenceCategory::WRITE) {
1154        return true;
1155    }
1156
1157    // we take `&mut` reference to variable: `&mut v`
1158    let path = match path_element_of_reference(node, reference) {
1159        Some(path) => path,
1160        None => return false,
1161    };
1162
1163    expr_require_exclusive_access(ctx, &path).unwrap_or(false)
1164}
1165
1166/// checks if this expr requires `&mut` access, recurses on field access
1167fn expr_require_exclusive_access(ctx: &AssistContext<'_>, expr: &ast::Expr) -> Option<bool> {
1168    if let ast::Expr::MacroExpr(_) = expr {
1169        // FIXME: expand macro and check output for mutable usages of the variable?
1170        return None;
1171    }
1172
1173    let parent = expr.syntax().parent()?;
1174
1175    if let Some(bin_expr) = ast::BinExpr::cast(parent.clone()) {
1176        if matches!(bin_expr.op_kind()?, ast::BinaryOp::Assignment { .. }) {
1177            return Some(bin_expr.lhs()?.syntax() == expr.syntax());
1178        }
1179        return Some(false);
1180    }
1181
1182    if let Some(ref_expr) = ast::RefExpr::cast(parent.clone()) {
1183        return Some(ref_expr.mut_token().is_some());
1184    }
1185
1186    if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
1187        let func = ctx.sema.resolve_method_call(&method_call)?;
1188        let self_param = func.self_param(ctx.db())?;
1189        let access = self_param.access(ctx.db());
1190
1191        return Some(matches!(access, hir::Access::Exclusive));
1192    }
1193
1194    if let Some(field) = ast::FieldExpr::cast(parent) {
1195        return expr_require_exclusive_access(ctx, &field.into());
1196    }
1197
1198    Some(false)
1199}
1200
1201trait HasTokenAtOffset {
1202    fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken>;
1203}
1204
1205impl HasTokenAtOffset for SyntaxNode {
1206    fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
1207        SyntaxNode::token_at_offset(self, offset)
1208    }
1209}
1210
1211impl HasTokenAtOffset for FunctionBody {
1212    fn token_at_offset(&self, offset: TextSize) -> TokenAtOffset<SyntaxToken> {
1213        match self {
1214            FunctionBody::Expr(expr) => expr.syntax().token_at_offset(offset),
1215            FunctionBody::Span { parent, text_range, .. } => {
1216                match parent.syntax().token_at_offset(offset) {
1217                    TokenAtOffset::None => TokenAtOffset::None,
1218                    TokenAtOffset::Single(t) => {
1219                        if text_range.contains_range(t.text_range()) {
1220                            TokenAtOffset::Single(t)
1221                        } else {
1222                            TokenAtOffset::None
1223                        }
1224                    }
1225                    TokenAtOffset::Between(a, b) => {
1226                        match (
1227                            text_range.contains_range(a.text_range()),
1228                            text_range.contains_range(b.text_range()),
1229                        ) {
1230                            (true, true) => TokenAtOffset::Between(a, b),
1231                            (true, false) => TokenAtOffset::Single(a),
1232                            (false, true) => TokenAtOffset::Single(b),
1233                            (false, false) => TokenAtOffset::None,
1234                        }
1235                    }
1236                }
1237            }
1238        }
1239    }
1240}
1241
1242/// find relevant `ast::Expr` for reference
1243///
1244/// # Preconditions
1245///
1246/// `node` must cover `reference`, that is `node.text_range().contains_range(reference.range)`
1247fn path_element_of_reference(
1248    node: &dyn HasTokenAtOffset,
1249    reference: &FileReference,
1250) -> Option<ast::Expr> {
1251    let token = node.token_at_offset(reference.range.start()).right_biased().or_else(|| {
1252        stdx::never!(false, "cannot find token at variable usage: {:?}", reference);
1253        None
1254    })?;
1255    let path = token.parent_ancestors().find_map(ast::Expr::cast).or_else(|| {
1256        stdx::never!(false, "cannot find path parent of variable usage: {:?}", token);
1257        None
1258    })?;
1259    stdx::always!(
1260        matches!(path, ast::Expr::PathExpr(_) | ast::Expr::MacroExpr(_)),
1261        "unexpected expression type for variable usage: {:?}",
1262        path
1263    );
1264    Some(path)
1265}
1266
1267/// list local variables defined inside `body`
1268fn locals_defined_in_body(
1269    sema: &Semantics<'_, RootDatabase>,
1270    body: &FunctionBody,
1271) -> FxIndexSet<Local> {
1272    // FIXME: this doesn't work well with macros
1273    //        see https://github.com/rust-lang/rust-analyzer/pull/7535#discussion_r570048550
1274    let mut res = FxIndexSet::default();
1275    body.walk_pat(&mut |pat| {
1276        if let ast::Pat::IdentPat(pat) = pat
1277            && let Some(local) = sema.to_def(&pat)
1278        {
1279            res.insert(local);
1280        }
1281    });
1282    res
1283}
1284
1285/// Returns usage details if local variable is used after(outside of) body
1286fn local_outlives_body(
1287    ctx: &AssistContext<'_>,
1288    body_range: TextRange,
1289    local: Local,
1290    parent: &SyntaxNode,
1291) -> Option<OutlivedLocal> {
1292    let usages = LocalUsages::find_local_usages(ctx, local);
1293    let mut has_mut_usages = false;
1294    let mut any_outlives = false;
1295    for usage in usages.iter() {
1296        if body_range.end() <= usage.range.start() {
1297            has_mut_usages |= reference_is_exclusive(usage, parent, ctx);
1298            any_outlives |= true;
1299            if has_mut_usages {
1300                break; // no need to check more elements we have all the info we wanted
1301            }
1302        }
1303    }
1304    if !any_outlives {
1305        return None;
1306    }
1307    Some(OutlivedLocal { local, mut_usage_outside_body: has_mut_usages })
1308}
1309
1310/// checks if the relevant local was defined before(outside of) body
1311fn is_defined_outside_of_body(
1312    ctx: &AssistContext<'_>,
1313    body: &FunctionBody,
1314    src: &LocalSource,
1315) -> bool {
1316    src.original_file(ctx.db()) == ctx.file_id() && !body.contains_node(src.syntax())
1317}
1318
1319/// find where to put extracted function definition
1320///
1321/// Function should be put right after returned node
1322fn node_to_insert_after(body: &FunctionBody, anchor: Anchor) -> Option<SyntaxNode> {
1323    let node = body.node();
1324    let mut ancestors = node.ancestors().peekable();
1325    let mut last_ancestor = None;
1326    while let Some(next_ancestor) = ancestors.next() {
1327        match next_ancestor.kind() {
1328            SyntaxKind::SOURCE_FILE => break,
1329            SyntaxKind::IMPL => {
1330                if body.extracted_from_trait_impl() && matches!(anchor, Anchor::Method) {
1331                    let impl_node = find_non_trait_impl(&next_ancestor);
1332                    if let target_node @ Some(_) = impl_node.as_ref().and_then(last_impl_member) {
1333                        return target_node;
1334                    }
1335                }
1336            }
1337            SyntaxKind::ITEM_LIST if !matches!(anchor, Anchor::Freestanding) => continue,
1338            SyntaxKind::ITEM_LIST => {
1339                if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::MODULE) {
1340                    break;
1341                }
1342            }
1343            SyntaxKind::ASSOC_ITEM_LIST if !matches!(anchor, Anchor::Method) => continue,
1344            SyntaxKind::ASSOC_ITEM_LIST if body.extracted_from_trait_impl() => continue,
1345            SyntaxKind::ASSOC_ITEM_LIST => {
1346                if ancestors.peek().map(SyntaxNode::kind) == Some(SyntaxKind::IMPL) {
1347                    break;
1348                }
1349            }
1350            _ => (),
1351        }
1352        last_ancestor = Some(next_ancestor);
1353    }
1354    last_ancestor
1355}
1356
1357fn find_non_trait_impl(trait_impl: &SyntaxNode) -> Option<ast::Impl> {
1358    let as_impl = ast::Impl::cast(trait_impl.clone())?;
1359    let impl_type = Some(impl_type_name(&as_impl)?);
1360
1361    let siblings = trait_impl.parent()?.children();
1362    siblings
1363        .filter_map(ast::Impl::cast)
1364        .find(|s| impl_type_name(s) == impl_type && !is_trait_impl(s))
1365}
1366
1367fn last_impl_member(impl_node: &ast::Impl) -> Option<SyntaxNode> {
1368    let last_child = impl_node.assoc_item_list()?.assoc_items().last()?;
1369    Some(last_child.syntax().clone())
1370}
1371
1372fn is_trait_impl(node: &ast::Impl) -> bool {
1373    node.trait_().is_some()
1374}
1375
1376fn impl_type_name(impl_node: &ast::Impl) -> Option<String> {
1377    Some(impl_node.self_ty()?.to_string())
1378}
1379
1380/// Fixes up the call site before the target expressions are replaced with the call expression
1381fn fixup_call_site(builder: &mut SourceChangeBuilder, body: &FunctionBody) {
1382    let parent_match_arm = body.parent().and_then(ast::MatchArm::cast);
1383
1384    if let Some(parent_match_arm) = parent_match_arm
1385        && parent_match_arm.comma_token().is_none()
1386    {
1387        let parent_match_arm = builder.make_mut(parent_match_arm);
1388        ted::append_child_raw(parent_match_arm.syntax(), make::token(T![,]));
1389    }
1390}
1391
1392fn make_call(ctx: &AssistContext<'_>, fun: &Function<'_>, indent: IndentLevel) -> SyntaxNode {
1393    let ret_ty = fun.return_type(ctx);
1394
1395    let args = make::arg_list(fun.params.iter().map(|param| param.to_arg(ctx, fun.mods.edition)));
1396    let name = fun.name.clone();
1397    let mut call_expr = if fun.self_param.is_some() {
1398        let self_arg = make::expr_path(make::ext::ident_path("self"));
1399        make::expr_method_call(self_arg, name, args).into()
1400    } else {
1401        let func = make::expr_path(make::path_unqualified(make::path_segment(name)));
1402        make::expr_call(func, args).into()
1403    };
1404
1405    let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1406
1407    if fun.control_flow.is_async {
1408        call_expr = make::expr_await(call_expr);
1409    }
1410
1411    let expr = handler.make_call_expr(call_expr).clone_for_update();
1412    expr.indent(indent);
1413
1414    let outliving_bindings = match fun.outliving_locals.as_slice() {
1415        [] => None,
1416        [var] => {
1417            let name = var.local.name(ctx.db());
1418            let name = make::name(&name.display(ctx.db(), fun.mods.edition).to_string());
1419            Some(ast::Pat::IdentPat(make::ident_pat(false, var.mut_usage_outside_body, name)))
1420        }
1421        vars => {
1422            let binding_pats = vars.iter().map(|var| {
1423                let name = var.local.name(ctx.db());
1424                let name = make::name(&name.display(ctx.db(), fun.mods.edition).to_string());
1425                make::ident_pat(false, var.mut_usage_outside_body, name).into()
1426            });
1427            Some(ast::Pat::TuplePat(make::tuple_pat(binding_pats)))
1428        }
1429    };
1430
1431    let parent_match_arm = fun.body.parent().and_then(ast::MatchArm::cast);
1432
1433    if let Some(bindings) = outliving_bindings {
1434        // with bindings that outlive it
1435        make::let_stmt(bindings, None, Some(expr)).syntax().clone_for_update()
1436    } else if parent_match_arm.as_ref().is_some() {
1437        // as a tail expr for a match arm
1438        expr.syntax().clone()
1439    } else if parent_match_arm.as_ref().is_none()
1440        && fun.ret_ty.is_unit()
1441        && (!fun.outliving_locals.is_empty() || !expr.is_block_like())
1442    {
1443        // as an expr stmt
1444        make::expr_stmt(expr).syntax().clone_for_update()
1445    } else {
1446        // as a tail expr, or a block
1447        expr.syntax().clone()
1448    }
1449}
1450
1451enum FlowHandler<'db> {
1452    None,
1453    Try { kind: TryKind<'db> },
1454    If { action: FlowKind<'db> },
1455    IfOption { action: FlowKind<'db> },
1456    MatchOption { none: FlowKind<'db> },
1457    MatchResult { err: FlowKind<'db> },
1458}
1459
1460impl<'db> FlowHandler<'db> {
1461    fn from_ret_ty(fun: &Function<'db>, ret_ty: &FunType<'db>) -> FlowHandler<'db> {
1462        if fun.contains_tail_expr {
1463            return FlowHandler::None;
1464        }
1465        let Some(action) = fun.control_flow.kind.clone() else {
1466            return FlowHandler::None;
1467        };
1468
1469        if let FunType::Unit = ret_ty {
1470            match action {
1471                FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
1472                    FlowHandler::If { action }
1473                }
1474                FlowKind::Return(_) | FlowKind::Break(_, _) => FlowHandler::IfOption { action },
1475                FlowKind::Try { kind } => FlowHandler::Try { kind },
1476            }
1477        } else {
1478            match action {
1479                FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
1480                    FlowHandler::MatchOption { none: action }
1481                }
1482                FlowKind::Return(_) | FlowKind::Break(_, _) => {
1483                    FlowHandler::MatchResult { err: action }
1484                }
1485                FlowKind::Try { kind } => FlowHandler::Try { kind },
1486            }
1487        }
1488    }
1489
1490    fn make_call_expr(&self, call_expr: ast::Expr) -> ast::Expr {
1491        match self {
1492            FlowHandler::None => call_expr,
1493            FlowHandler::Try { kind: _ } => make::expr_try(call_expr),
1494            FlowHandler::If { action } => {
1495                let action = action.make_result_handler(None);
1496                let stmt = make::expr_stmt(action);
1497                let block = make::block_expr(iter::once(stmt.into()), None);
1498                let controlflow_break_path = make::path_from_text("ControlFlow::Break");
1499                let condition = make::expr_let(
1500                    make::tuple_struct_pat(
1501                        controlflow_break_path,
1502                        iter::once(make::wildcard_pat().into()),
1503                    )
1504                    .into(),
1505                    call_expr,
1506                );
1507                make::expr_if(condition.into(), block, None).into()
1508            }
1509            FlowHandler::IfOption { action } => {
1510                let path = make::ext::ident_path("Some");
1511                let value_pat = make::ext::simple_ident_pat(make::name("value"));
1512                let pattern = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1513                let cond = make::expr_let(pattern.into(), call_expr);
1514                let value = make::expr_path(make::ext::ident_path("value"));
1515                let action_expr = action.make_result_handler(Some(value));
1516                let action_stmt = make::expr_stmt(action_expr);
1517                let then = make::block_expr(iter::once(action_stmt.into()), None);
1518                make::expr_if(cond.into(), then, None).into()
1519            }
1520            FlowHandler::MatchOption { none } => {
1521                let some_name = "value";
1522
1523                let some_arm = {
1524                    let path = make::ext::ident_path("Some");
1525                    let value_pat = make::ext::simple_ident_pat(make::name(some_name));
1526                    let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1527                    let value = make::expr_path(make::ext::ident_path(some_name));
1528                    make::match_arm(pat.into(), None, value)
1529                };
1530                let none_arm = {
1531                    let path = make::ext::ident_path("None");
1532                    let pat = make::path_pat(path);
1533                    make::match_arm(pat, None, none.make_result_handler(None))
1534                };
1535                let arms = make::match_arm_list(vec![some_arm, none_arm]);
1536                make::expr_match(call_expr, arms).into()
1537            }
1538            FlowHandler::MatchResult { err } => {
1539                let ok_name = "value";
1540                let err_name = "value";
1541
1542                let ok_arm = {
1543                    let path = make::ext::ident_path("Ok");
1544                    let value_pat = make::ext::simple_ident_pat(make::name(ok_name));
1545                    let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1546                    let value = make::expr_path(make::ext::ident_path(ok_name));
1547                    make::match_arm(pat.into(), None, value)
1548                };
1549                let err_arm = {
1550                    let path = make::ext::ident_path("Err");
1551                    let value_pat = make::ext::simple_ident_pat(make::name(err_name));
1552                    let pat = make::tuple_struct_pat(path, iter::once(value_pat.into()));
1553                    let value = make::expr_path(make::ext::ident_path(err_name));
1554                    make::match_arm(pat.into(), None, err.make_result_handler(Some(value)))
1555                };
1556                let arms = make::match_arm_list(vec![ok_arm, err_arm]);
1557                make::expr_match(call_expr, arms).into()
1558            }
1559        }
1560    }
1561}
1562
1563fn path_expr_from_local(ctx: &AssistContext<'_>, var: Local, edition: Edition) -> ast::Expr {
1564    let name = var.name(ctx.db()).display(ctx.db(), edition).to_string();
1565    make::expr_path(make::ext::ident_path(&name))
1566}
1567
1568fn format_function(
1569    ctx: &AssistContext<'_>,
1570    module: hir::Module,
1571    fun: &Function<'_>,
1572    old_indent: IndentLevel,
1573) -> ast::Fn {
1574    let fun_name = make::name(&fun.name.text());
1575    let params = fun.make_param_list(ctx, module, fun.mods.edition);
1576    let ret_ty = fun.make_ret_ty(ctx, module);
1577    let body = make_body(ctx, old_indent, fun);
1578    let (generic_params, where_clause) = make_generic_params_and_where_clause(ctx, fun);
1579
1580    make::fn_(
1581        None,
1582        None,
1583        fun_name,
1584        generic_params,
1585        where_clause,
1586        params,
1587        body,
1588        ret_ty,
1589        fun.control_flow.is_async,
1590        fun.mods.is_const,
1591        fun.control_flow.is_unsafe,
1592        false,
1593    )
1594}
1595
1596fn make_generic_params_and_where_clause(
1597    ctx: &AssistContext<'_>,
1598    fun: &Function<'_>,
1599) -> (Option<ast::GenericParamList>, Option<ast::WhereClause>) {
1600    let used_type_params = fun.type_params(ctx);
1601
1602    let generic_param_list = make_generic_param_list(ctx, fun, &used_type_params);
1603    let where_clause = make_where_clause(ctx, fun, &used_type_params);
1604
1605    (generic_param_list, where_clause)
1606}
1607
1608fn make_generic_param_list(
1609    ctx: &AssistContext<'_>,
1610    fun: &Function<'_>,
1611    used_type_params: &[TypeParam],
1612) -> Option<ast::GenericParamList> {
1613    let mut generic_params = fun
1614        .mods
1615        .generic_param_lists
1616        .iter()
1617        .flat_map(|parent_params| {
1618            parent_params
1619                .generic_params()
1620                .filter(|param| param_is_required(ctx, param, used_type_params))
1621        })
1622        .peekable();
1623
1624    if generic_params.peek().is_some() {
1625        Some(make::generic_param_list(generic_params))
1626    } else {
1627        None
1628    }
1629}
1630
1631fn param_is_required(
1632    ctx: &AssistContext<'_>,
1633    param: &ast::GenericParam,
1634    used_type_params: &[TypeParam],
1635) -> bool {
1636    match param {
1637        ast::GenericParam::ConstParam(_) | ast::GenericParam::LifetimeParam(_) => false,
1638        ast::GenericParam::TypeParam(type_param) => match &ctx.sema.to_def(type_param) {
1639            Some(def) => used_type_params.contains(def),
1640            _ => false,
1641        },
1642    }
1643}
1644
1645fn make_where_clause(
1646    ctx: &AssistContext<'_>,
1647    fun: &Function<'_>,
1648    used_type_params: &[TypeParam],
1649) -> Option<ast::WhereClause> {
1650    let mut predicates = fun
1651        .mods
1652        .where_clauses
1653        .iter()
1654        .flat_map(|parent_where_clause| {
1655            parent_where_clause
1656                .predicates()
1657                .filter(|pred| pred_is_required(ctx, pred, used_type_params))
1658        })
1659        .peekable();
1660
1661    if predicates.peek().is_some() { Some(make::where_clause(predicates)) } else { None }
1662}
1663
1664fn pred_is_required(
1665    ctx: &AssistContext<'_>,
1666    pred: &ast::WherePred,
1667    used_type_params: &[TypeParam],
1668) -> bool {
1669    match resolved_type_param(ctx, pred) {
1670        Some(it) => used_type_params.contains(&it),
1671        None => false,
1672    }
1673}
1674
1675fn resolved_type_param(ctx: &AssistContext<'_>, pred: &ast::WherePred) -> Option<TypeParam> {
1676    let path = match pred.ty()? {
1677        ast::Type::PathType(path_type) => path_type.path(),
1678        _ => None,
1679    }?;
1680
1681    match ctx.sema.resolve_path(&path)? {
1682        PathResolution::TypeParam(type_param) => Some(type_param),
1683        _ => None,
1684    }
1685}
1686
1687impl<'db> Function<'db> {
1688    /// Collect all the `TypeParam`s used in the `body` and `params`.
1689    fn type_params(&self, ctx: &AssistContext<'db>) -> Vec<TypeParam> {
1690        let type_params_in_descendant_paths =
1691            self.body.descendant_paths().filter_map(|it| match ctx.sema.resolve_path(&it) {
1692                Some(PathResolution::TypeParam(type_param)) => Some(type_param),
1693                _ => None,
1694            });
1695        let type_params_in_params = self.params.iter().filter_map(|p| p.ty.as_type_param(ctx.db()));
1696        type_params_in_descendant_paths.chain(type_params_in_params).collect()
1697    }
1698
1699    fn make_param_list(
1700        &self,
1701        ctx: &AssistContext<'_>,
1702        module: hir::Module,
1703        edition: Edition,
1704    ) -> ast::ParamList {
1705        let self_param = self.self_param.clone();
1706        let params = self.params.iter().map(|param| param.to_param(ctx, module, edition));
1707        make::param_list(self_param, params)
1708    }
1709
1710    fn make_ret_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> Option<ast::RetType> {
1711        let fun_ty = self.return_type(ctx);
1712        let handler = FlowHandler::from_ret_ty(self, &fun_ty);
1713        let ret_ty = match &handler {
1714            FlowHandler::None => {
1715                if matches!(fun_ty, FunType::Unit) {
1716                    return None;
1717                }
1718                fun_ty.make_ty(ctx, module)
1719            }
1720            FlowHandler::Try { kind: TryKind::Option } => {
1721                make::ext::ty_option(fun_ty.make_ty(ctx, module))
1722            }
1723            FlowHandler::Try { kind: TryKind::Result { ty: parent_ret_ty } } => {
1724                let handler_ty = parent_ret_ty
1725                    .type_arguments()
1726                    .nth(1)
1727                    .map(|ty| make_ty(&ty, ctx, module))
1728                    .unwrap_or_else(make::ty_placeholder);
1729                make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1730            }
1731            FlowHandler::If { .. } => make::ty("ControlFlow<()>"),
1732            FlowHandler::IfOption { action } => {
1733                let handler_ty = action
1734                    .expr_ty(ctx)
1735                    .map(|ty| make_ty(&ty, ctx, module))
1736                    .unwrap_or_else(make::ty_placeholder);
1737                make::ext::ty_option(handler_ty)
1738            }
1739            FlowHandler::MatchOption { .. } => make::ext::ty_option(fun_ty.make_ty(ctx, module)),
1740            FlowHandler::MatchResult { err } => {
1741                let handler_ty = err
1742                    .expr_ty(ctx)
1743                    .map(|ty| make_ty(&ty, ctx, module))
1744                    .unwrap_or_else(make::ty_placeholder);
1745                make::ext::ty_result(fun_ty.make_ty(ctx, module), handler_ty)
1746            }
1747        };
1748        Some(make::ret_type(ret_ty))
1749    }
1750}
1751
1752impl<'db> FunType<'db> {
1753    fn make_ty(&self, ctx: &AssistContext<'db>, module: hir::Module) -> ast::Type {
1754        match self {
1755            FunType::Unit => make::ty_unit(),
1756            FunType::Single(ty) => make_ty(ty, ctx, module),
1757            FunType::Tuple(types) => match types.as_slice() {
1758                [] => {
1759                    stdx::never!("tuple type with 0 elements");
1760                    make::ty_unit()
1761                }
1762                [ty] => {
1763                    stdx::never!("tuple type with 1 element");
1764                    make_ty(ty, ctx, module)
1765                }
1766                types => {
1767                    let types = types.iter().map(|ty| make_ty(ty, ctx, module));
1768                    make::ty_tuple(types)
1769                }
1770            },
1771        }
1772    }
1773}
1774
1775fn make_body(
1776    ctx: &AssistContext<'_>,
1777    old_indent: IndentLevel,
1778    fun: &Function<'_>,
1779) -> ast::BlockExpr {
1780    let ret_ty = fun.return_type(ctx);
1781    let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
1782
1783    let block = match &fun.body {
1784        FunctionBody::Expr(expr) => {
1785            let expr = rewrite_body_segment(ctx, &fun.params, &handler, expr.syntax());
1786            let expr = ast::Expr::cast(expr).expect("Body segment should be an expr");
1787            match expr {
1788                ast::Expr::BlockExpr(block) => {
1789                    // If the extracted expression is itself a block, there is no need to wrap it inside another block.
1790                    block.dedent(old_indent);
1791                    let elements = block.stmt_list().map_or_else(
1792                        || Either::Left(iter::empty()),
1793                        |stmt_list| {
1794                            let elements = stmt_list.syntax().children_with_tokens().filter_map(
1795                                |node_or_token| match &node_or_token {
1796                                    syntax::NodeOrToken::Node(node) => {
1797                                        ast::Stmt::cast(node.clone()).map(|_| node_or_token)
1798                                    }
1799                                    syntax::NodeOrToken::Token(token) => {
1800                                        ast::Comment::cast(token.clone()).map(|_| node_or_token)
1801                                    }
1802                                },
1803                            );
1804                            Either::Right(elements)
1805                        },
1806                    );
1807                    make::hacky_block_expr(elements, block.tail_expr())
1808                }
1809                _ => {
1810                    expr.reindent_to(1.into());
1811
1812                    make::block_expr(Vec::new(), Some(expr))
1813                }
1814            }
1815        }
1816        FunctionBody::Span { parent, text_range, .. } => {
1817            let mut elements: Vec<_> = parent
1818                .syntax()
1819                .children_with_tokens()
1820                .filter(|it| text_range.contains_range(it.text_range()))
1821                .map(|it| match &it {
1822                    syntax::NodeOrToken::Node(n) => syntax::NodeOrToken::Node(
1823                        rewrite_body_segment(ctx, &fun.params, &handler, n),
1824                    ),
1825                    _ => it,
1826                })
1827                .collect();
1828
1829            let mut tail_expr = match &elements.last() {
1830                Some(syntax::NodeOrToken::Node(node)) if ast::Expr::can_cast(node.kind()) => {
1831                    ast::Expr::cast(node.clone())
1832                }
1833                _ => None,
1834            };
1835
1836            match tail_expr {
1837                Some(_) => {
1838                    elements.pop();
1839                }
1840                None => match fun.outliving_locals.as_slice() {
1841                    [] => {}
1842                    [var] => {
1843                        tail_expr = Some(path_expr_from_local(ctx, var.local, fun.mods.edition));
1844                    }
1845                    vars => {
1846                        let exprs = vars
1847                            .iter()
1848                            .map(|var| path_expr_from_local(ctx, var.local, fun.mods.edition));
1849                        let expr = make::expr_tuple(exprs);
1850                        tail_expr = Some(expr.into());
1851                    }
1852                },
1853            };
1854
1855            let body_indent = IndentLevel(1);
1856            let elements = elements
1857                .into_iter()
1858                .map(|node_or_token| match &node_or_token {
1859                    syntax::NodeOrToken::Node(node) => match ast::Stmt::cast(node.clone()) {
1860                        Some(stmt) => {
1861                            stmt.reindent_to(body_indent);
1862                            let ast_node = stmt.syntax().clone_subtree();
1863                            syntax::NodeOrToken::Node(ast_node)
1864                        }
1865                        _ => node_or_token,
1866                    },
1867                    _ => node_or_token,
1868                })
1869                .collect::<Vec<SyntaxElement>>();
1870            if let Some(tail_expr) = &mut tail_expr {
1871                tail_expr.reindent_to(body_indent);
1872            }
1873
1874            make::hacky_block_expr(elements, tail_expr)
1875        }
1876    };
1877
1878    match &handler {
1879        FlowHandler::None => block,
1880        FlowHandler::Try { kind } => {
1881            let block = with_default_tail_expr(block, make::ext::expr_unit());
1882            map_tail_expr(block, |tail_expr| {
1883                let constructor = match kind {
1884                    TryKind::Option => "Some",
1885                    TryKind::Result { .. } => "Ok",
1886                };
1887                let func = make::expr_path(make::ext::ident_path(constructor));
1888                let args = make::arg_list(iter::once(tail_expr));
1889                make::expr_call(func, args).into()
1890            })
1891        }
1892        FlowHandler::If { .. } => {
1893            let controlflow_continue = make::expr_call(
1894                make::expr_path(make::path_from_text("ControlFlow::Continue")),
1895                make::arg_list([make::ext::expr_unit()]),
1896            )
1897            .into();
1898            with_tail_expr(block, controlflow_continue)
1899        }
1900        FlowHandler::IfOption { .. } => {
1901            let none = make::expr_path(make::ext::ident_path("None"));
1902            with_tail_expr(block, none)
1903        }
1904        FlowHandler::MatchOption { .. } => map_tail_expr(block, |tail_expr| {
1905            let some = make::expr_path(make::ext::ident_path("Some"));
1906            let args = make::arg_list(iter::once(tail_expr));
1907            make::expr_call(some, args).into()
1908        }),
1909        FlowHandler::MatchResult { .. } => map_tail_expr(block, |tail_expr| {
1910            let ok = make::expr_path(make::ext::ident_path("Ok"));
1911            let args = make::arg_list(iter::once(tail_expr));
1912            make::expr_call(ok, args).into()
1913        }),
1914    }
1915}
1916
1917fn map_tail_expr(block: ast::BlockExpr, f: impl FnOnce(ast::Expr) -> ast::Expr) -> ast::BlockExpr {
1918    let tail_expr = match block.tail_expr() {
1919        Some(tail_expr) => tail_expr,
1920        None => return block,
1921    };
1922    make::block_expr(block.statements(), Some(f(tail_expr)))
1923}
1924
1925fn with_default_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1926    match block.tail_expr() {
1927        Some(_) => block,
1928        None => make::block_expr(block.statements(), Some(tail_expr)),
1929    }
1930}
1931
1932fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr {
1933    let stmt_tail_opt: Option<ast::Stmt> =
1934        block.tail_expr().map(|expr| make::expr_stmt(expr).into());
1935
1936    let mut elements: Vec<SyntaxElement> = vec![];
1937
1938    block.statements().for_each(|stmt| {
1939        elements.push(syntax::NodeOrToken::Node(stmt.syntax().clone()));
1940    });
1941
1942    if let Some(stmt_list) = block.stmt_list() {
1943        stmt_list.syntax().children_with_tokens().for_each(|node_or_token| {
1944            if let syntax::NodeOrToken::Token(_) = &node_or_token {
1945                elements.push(node_or_token)
1946            };
1947        });
1948    }
1949
1950    if let Some(stmt_tail) = stmt_tail_opt {
1951        elements.push(syntax::NodeOrToken::Node(stmt_tail.syntax().clone()));
1952    }
1953
1954    make::hacky_block_expr(elements, Some(tail_expr))
1955}
1956
1957fn format_type(ty: &hir::Type<'_>, ctx: &AssistContext<'_>, module: hir::Module) -> String {
1958    ty.display_source_code(ctx.db(), module.into(), true).ok().unwrap_or_else(|| "_".to_owned())
1959}
1960
1961fn make_ty(ty: &hir::Type<'_>, ctx: &AssistContext<'_>, module: hir::Module) -> ast::Type {
1962    let ty_str = format_type(ty, ctx, module);
1963    make::ty(&ty_str)
1964}
1965
1966fn rewrite_body_segment(
1967    ctx: &AssistContext<'_>,
1968    params: &[Param<'_>],
1969    handler: &FlowHandler<'_>,
1970    syntax: &SyntaxNode,
1971) -> SyntaxNode {
1972    let syntax = fix_param_usages(ctx, params, syntax);
1973    update_external_control_flow(handler, &syntax);
1974    syntax
1975}
1976
1977/// change all usages to account for added `&`/`&mut` for some params
1978fn fix_param_usages(
1979    ctx: &AssistContext<'_>,
1980    params: &[Param<'_>],
1981    syntax: &SyntaxNode,
1982) -> SyntaxNode {
1983    let mut usages_for_param: Vec<(&Param<'_>, Vec<ast::Expr>)> = Vec::new();
1984
1985    let tm = TreeMutator::new(syntax);
1986
1987    for param in params {
1988        if !param.kind().is_ref() {
1989            continue;
1990        }
1991
1992        let usages = LocalUsages::find_local_usages(ctx, param.var);
1993        let usages = usages
1994            .iter()
1995            .filter(|reference| syntax.text_range().contains_range(reference.range))
1996            .filter_map(|reference| path_element_of_reference(syntax, reference))
1997            .map(|expr| tm.make_mut(&expr));
1998
1999        usages_for_param.push((param, usages.unique().collect()));
2000    }
2001
2002    let res = tm.make_syntax_mut(syntax);
2003
2004    for (param, usages) in usages_for_param {
2005        for usage in usages {
2006            match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
2007                Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
2008                    // do nothing
2009                }
2010                Some(ast::Expr::RefExpr(node))
2011                    if param.kind() == ParamKind::MutRef && node.mut_token().is_some() =>
2012                {
2013                    ted::replace(
2014                        node.syntax(),
2015                        node.expr().expect("RefExpr::expr() cannot be None").syntax(),
2016                    );
2017                }
2018                Some(ast::Expr::RefExpr(node))
2019                    if param.kind() == ParamKind::SharedRef && node.mut_token().is_none() =>
2020                {
2021                    ted::replace(
2022                        node.syntax(),
2023                        node.expr().expect("RefExpr::expr() cannot be None").syntax(),
2024                    );
2025                }
2026                Some(_) | None => {
2027                    let p = &make::expr_prefix(T![*], usage.clone()).clone_for_update();
2028                    ted::replace(usage.syntax(), p.syntax())
2029                }
2030            }
2031        }
2032    }
2033
2034    res
2035}
2036
2037fn update_external_control_flow(handler: &FlowHandler<'_>, syntax: &SyntaxNode) {
2038    let mut nested_loop = None;
2039    let mut nested_scope = None;
2040    for event in syntax.preorder() {
2041        match event {
2042            WalkEvent::Enter(e) => match e.kind() {
2043                SyntaxKind::LOOP_EXPR | SyntaxKind::WHILE_EXPR | SyntaxKind::FOR_EXPR => {
2044                    if nested_loop.is_none() {
2045                        nested_loop = Some(e.clone());
2046                    }
2047                }
2048                SyntaxKind::FN
2049                | SyntaxKind::CONST
2050                | SyntaxKind::STATIC
2051                | SyntaxKind::IMPL
2052                | SyntaxKind::MODULE => {
2053                    if nested_scope.is_none() {
2054                        nested_scope = Some(e.clone());
2055                    }
2056                }
2057                _ => {}
2058            },
2059            WalkEvent::Leave(e) => {
2060                if nested_scope.is_none()
2061                    && let Some(expr) = ast::Expr::cast(e.clone())
2062                {
2063                    match expr {
2064                        ast::Expr::ReturnExpr(return_expr) => {
2065                            let expr = return_expr.expr();
2066                            if let Some(replacement) = make_rewritten_flow(handler, expr) {
2067                                ted::replace(return_expr.syntax(), replacement.syntax())
2068                            }
2069                        }
2070                        ast::Expr::BreakExpr(break_expr) if nested_loop.is_none() => {
2071                            let expr = break_expr.expr();
2072                            if let Some(replacement) = make_rewritten_flow(handler, expr) {
2073                                ted::replace(break_expr.syntax(), replacement.syntax())
2074                            }
2075                        }
2076                        ast::Expr::ContinueExpr(continue_expr) if nested_loop.is_none() => {
2077                            if let Some(replacement) = make_rewritten_flow(handler, None) {
2078                                ted::replace(continue_expr.syntax(), replacement.syntax())
2079                            }
2080                        }
2081                        _ => {
2082                            // do nothing
2083                        }
2084                    }
2085                }
2086
2087                if nested_loop.as_ref() == Some(&e) {
2088                    nested_loop = None;
2089                }
2090                if nested_scope.as_ref() == Some(&e) {
2091                    nested_scope = None;
2092                }
2093            }
2094        };
2095    }
2096}
2097
2098fn make_rewritten_flow(
2099    handler: &FlowHandler<'_>,
2100    arg_expr: Option<ast::Expr>,
2101) -> Option<ast::Expr> {
2102    let value = match handler {
2103        FlowHandler::None | FlowHandler::Try { .. } => return None,
2104        FlowHandler::If { .. } => make::expr_call(
2105            make::expr_path(make::path_from_text("ControlFlow::Break")),
2106            make::arg_list([make::ext::expr_unit()]),
2107        )
2108        .into(),
2109        FlowHandler::IfOption { .. } => {
2110            let expr = arg_expr.unwrap_or_else(make::ext::expr_unit);
2111            let args = make::arg_list([expr]);
2112            make::expr_call(make::expr_path(make::ext::ident_path("Some")), args).into()
2113        }
2114        FlowHandler::MatchOption { .. } => make::expr_path(make::ext::ident_path("None")),
2115        FlowHandler::MatchResult { .. } => {
2116            let expr = arg_expr.unwrap_or_else(make::ext::expr_unit);
2117            let args = make::arg_list([expr]);
2118            make::expr_call(make::expr_path(make::ext::ident_path("Err")), args).into()
2119        }
2120    };
2121    Some(make::expr_return(Some(value)).clone_for_update())
2122}
2123
2124#[cfg(test)]
2125mod tests {
2126    use crate::tests::{check_assist, check_assist_not_applicable};
2127
2128    use super::*;
2129
2130    #[test]
2131    fn no_args_from_binary_expr() {
2132        check_assist(
2133            extract_function,
2134            r#"
2135fn foo() {
2136    foo($01 + 1$0);
2137}
2138"#,
2139            r#"
2140fn foo() {
2141    foo(fun_name());
2142}
2143
2144fn $0fun_name() -> i32 {
2145    1 + 1
2146}
2147"#,
2148        );
2149    }
2150
2151    #[test]
2152    fn no_args_from_binary_expr_in_module() {
2153        check_assist(
2154            extract_function,
2155            r#"
2156mod bar {
2157    fn foo() {
2158        foo($01 + 1$0);
2159    }
2160}
2161"#,
2162            r#"
2163mod bar {
2164    fn foo() {
2165        foo(fun_name());
2166    }
2167
2168    fn $0fun_name() -> i32 {
2169        1 + 1
2170    }
2171}
2172"#,
2173        );
2174    }
2175
2176    #[test]
2177    fn no_args_from_binary_expr_indented() {
2178        check_assist(
2179            extract_function,
2180            r#"
2181fn foo() {
2182    $0{ 1 + 1 }$0;
2183}
2184"#,
2185            r#"
2186fn foo() {
2187    fun_name();
2188}
2189
2190fn $0fun_name() -> i32 {
2191    1 + 1
2192}
2193"#,
2194        );
2195    }
2196
2197    #[test]
2198    fn no_args_from_stmt_with_last_expr() {
2199        check_assist(
2200            extract_function,
2201            r#"
2202fn foo() -> i32 {
2203    let k = 1;
2204    $0let m = 1;
2205    m + 1$0
2206}
2207"#,
2208            r#"
2209fn foo() -> i32 {
2210    let k = 1;
2211    fun_name()
2212}
2213
2214fn $0fun_name() -> i32 {
2215    let m = 1;
2216    m + 1
2217}
2218"#,
2219        );
2220    }
2221
2222    #[test]
2223    fn no_args_from_stmt_unit() {
2224        check_assist(
2225            extract_function,
2226            r#"
2227fn foo() {
2228    let k = 3;
2229    $0let m = 1;
2230    let n = m + 1;$0
2231    let g = 5;
2232}
2233"#,
2234            r#"
2235fn foo() {
2236    let k = 3;
2237    fun_name();
2238    let g = 5;
2239}
2240
2241fn $0fun_name() {
2242    let m = 1;
2243    let n = m + 1;
2244}
2245"#,
2246        );
2247    }
2248
2249    #[test]
2250    fn no_args_if() {
2251        check_assist(
2252            extract_function,
2253            r#"
2254fn foo() {
2255    $0if true { }$0
2256}
2257"#,
2258            r#"
2259fn foo() {
2260    fun_name();
2261}
2262
2263fn $0fun_name() {
2264    if true { }
2265}
2266"#,
2267        );
2268    }
2269
2270    #[test]
2271    fn no_args_if_else() {
2272        check_assist(
2273            extract_function,
2274            r#"
2275fn foo() -> i32 {
2276    $0if true { 1 } else { 2 }$0
2277}
2278"#,
2279            r#"
2280fn foo() -> i32 {
2281    fun_name()
2282}
2283
2284fn $0fun_name() -> i32 {
2285    if true { 1 } else { 2 }
2286}
2287"#,
2288        );
2289    }
2290
2291    #[test]
2292    fn no_args_if_let_else() {
2293        check_assist(
2294            extract_function,
2295            r#"
2296fn foo() -> i32 {
2297    $0if let true = false { 1 } else { 2 }$0
2298}
2299"#,
2300            r#"
2301fn foo() -> i32 {
2302    fun_name()
2303}
2304
2305fn $0fun_name() -> i32 {
2306    if let true = false { 1 } else { 2 }
2307}
2308"#,
2309        );
2310    }
2311
2312    #[test]
2313    fn no_args_match() {
2314        check_assist(
2315            extract_function,
2316            r#"
2317fn foo() -> i32 {
2318    $0match true {
2319        true => 1,
2320        false => 2,
2321    }$0
2322}
2323"#,
2324            r#"
2325fn foo() -> i32 {
2326    fun_name()
2327}
2328
2329fn $0fun_name() -> i32 {
2330    match true {
2331        true => 1,
2332        false => 2,
2333    }
2334}
2335"#,
2336        );
2337    }
2338
2339    #[test]
2340    fn no_args_while() {
2341        check_assist(
2342            extract_function,
2343            r#"
2344fn foo() {
2345    $0while true { }$0
2346}
2347"#,
2348            r#"
2349fn foo() {
2350    fun_name();
2351}
2352
2353fn $0fun_name() {
2354    while true { }
2355}
2356"#,
2357        );
2358    }
2359
2360    #[test]
2361    fn no_args_for() {
2362        check_assist(
2363            extract_function,
2364            r#"
2365fn foo() {
2366    $0for v in &[0, 1] { }$0
2367}
2368"#,
2369            r#"
2370fn foo() {
2371    fun_name();
2372}
2373
2374fn $0fun_name() {
2375    for v in &[0, 1] { }
2376}
2377"#,
2378        );
2379    }
2380
2381    #[test]
2382    fn no_args_from_loop_unit() {
2383        check_assist(
2384            extract_function,
2385            r#"
2386fn foo() {
2387    $0loop {
2388        let m = 1;
2389    }$0
2390}
2391"#,
2392            r#"
2393fn foo() {
2394    fun_name()
2395}
2396
2397fn $0fun_name() -> ! {
2398    loop {
2399        let m = 1;
2400    }
2401}
2402"#,
2403        );
2404    }
2405
2406    #[test]
2407    fn no_args_from_loop_with_return() {
2408        check_assist(
2409            extract_function,
2410            r#"
2411fn foo() {
2412    let v = $0loop {
2413        let m = 1;
2414        break m;
2415    }$0;
2416}
2417"#,
2418            r#"
2419fn foo() {
2420    let v = fun_name();
2421}
2422
2423fn $0fun_name() -> i32 {
2424    loop {
2425        let m = 1;
2426        break m;
2427    }
2428}
2429"#,
2430        );
2431    }
2432
2433    #[test]
2434    fn no_args_from_match() {
2435        check_assist(
2436            extract_function,
2437            r#"
2438fn foo() {
2439    let v: i32 = $0match Some(1) {
2440        Some(x) => x,
2441        None => 0,
2442    }$0;
2443}
2444"#,
2445            r#"
2446fn foo() {
2447    let v: i32 = fun_name();
2448}
2449
2450fn $0fun_name() -> i32 {
2451    match Some(1) {
2452        Some(x) => x,
2453        None => 0,
2454    }
2455}
2456"#,
2457        );
2458    }
2459
2460    #[test]
2461    fn extract_partial_block_single_line() {
2462        check_assist(
2463            extract_function,
2464            r#"
2465fn foo() {
2466    let n = 1;
2467    let mut v = $0n * n;$0
2468    v += 1;
2469}
2470"#,
2471            r#"
2472fn foo() {
2473    let n = 1;
2474    let mut v = fun_name(n);
2475    v += 1;
2476}
2477
2478fn $0fun_name(n: i32) -> i32 {
2479    let mut v = n * n;
2480    v
2481}
2482"#,
2483        );
2484    }
2485
2486    #[test]
2487    fn extract_partial_block() {
2488        check_assist(
2489            extract_function,
2490            r#"
2491fn foo() {
2492    let m = 2;
2493    let n = 1;
2494    let mut v = m $0* n;
2495    let mut w = 3;$0
2496    v += 1;
2497    w += 1;
2498}
2499"#,
2500            r#"
2501fn foo() {
2502    let m = 2;
2503    let n = 1;
2504    let (mut v, mut w) = fun_name(m, n);
2505    v += 1;
2506    w += 1;
2507}
2508
2509fn $0fun_name(m: i32, n: i32) -> (i32, i32) {
2510    let mut v = m * n;
2511    let mut w = 3;
2512    (v, w)
2513}
2514"#,
2515        );
2516    }
2517
2518    #[test]
2519    fn argument_form_expr() {
2520        check_assist(
2521            extract_function,
2522            r#"
2523fn foo() -> u32 {
2524    let n = 2;
2525    $0n+2$0
2526}
2527"#,
2528            r#"
2529fn foo() -> u32 {
2530    let n = 2;
2531    fun_name(n)
2532}
2533
2534fn $0fun_name(n: u32) -> u32 {
2535    n+2
2536}
2537"#,
2538        )
2539    }
2540
2541    #[test]
2542    fn argument_used_twice_form_expr() {
2543        check_assist(
2544            extract_function,
2545            r#"
2546fn foo() -> u32 {
2547    let n = 2;
2548    $0n+n$0
2549}
2550"#,
2551            r#"
2552fn foo() -> u32 {
2553    let n = 2;
2554    fun_name(n)
2555}
2556
2557fn $0fun_name(n: u32) -> u32 {
2558    n+n
2559}
2560"#,
2561        )
2562    }
2563
2564    #[test]
2565    fn two_arguments_form_expr() {
2566        check_assist(
2567            extract_function,
2568            r#"
2569fn foo() -> u32 {
2570    let n = 2;
2571    let m = 3;
2572    $0n+n*m$0
2573}
2574"#,
2575            r#"
2576fn foo() -> u32 {
2577    let n = 2;
2578    let m = 3;
2579    fun_name(n, m)
2580}
2581
2582fn $0fun_name(n: u32, m: u32) -> u32 {
2583    n+n*m
2584}
2585"#,
2586        )
2587    }
2588
2589    #[test]
2590    fn argument_and_locals() {
2591        check_assist(
2592            extract_function,
2593            r#"
2594fn foo() -> u32 {
2595    let n = 2;
2596    $0let m = 1;
2597    n + m$0
2598}
2599"#,
2600            r#"
2601fn foo() -> u32 {
2602    let n = 2;
2603    fun_name(n)
2604}
2605
2606fn $0fun_name(n: u32) -> u32 {
2607    let m = 1;
2608    n + m
2609}
2610"#,
2611        )
2612    }
2613
2614    #[test]
2615    fn in_comment_is_not_applicable() {
2616        cov_mark::check!(extract_function_in_comment_is_not_applicable);
2617        check_assist_not_applicable(extract_function, r"fn main() { 1 + /* $0comment$0 */ 1; }");
2618    }
2619
2620    #[test]
2621    fn empty_selection_is_not_applicable() {
2622        cov_mark::check!(extract_function_empty_selection_is_not_applicable);
2623        check_assist_not_applicable(
2624            extract_function,
2625            r#"
2626fn main() {
2627    $0
2628
2629    $0
2630}"#,
2631        );
2632    }
2633
2634    #[test]
2635    fn part_of_expr_stmt() {
2636        check_assist(
2637            extract_function,
2638            r#"
2639fn foo() {
2640    $01$0 + 1;
2641}
2642"#,
2643            r#"
2644fn foo() {
2645    fun_name() + 1;
2646}
2647
2648fn $0fun_name() -> i32 {
2649    1
2650}
2651"#,
2652        );
2653    }
2654
2655    #[test]
2656    fn function_expr() {
2657        check_assist(
2658            extract_function,
2659            r#"
2660fn foo() {
2661    $0bar(1 + 1)$0
2662}
2663"#,
2664            r#"
2665fn foo() {
2666    fun_name();
2667}
2668
2669fn $0fun_name() {
2670    bar(1 + 1)
2671}
2672"#,
2673        )
2674    }
2675
2676    #[test]
2677    fn extract_from_nested() {
2678        check_assist(
2679            extract_function,
2680            r#"
2681fn main() {
2682    let x = true;
2683    let tuple = match x {
2684        true => ($02 + 2$0, true)
2685        _ => (0, false)
2686    };
2687}
2688"#,
2689            r#"
2690fn main() {
2691    let x = true;
2692    let tuple = match x {
2693        true => (fun_name(), true)
2694        _ => (0, false)
2695    };
2696}
2697
2698fn $0fun_name() -> i32 {
2699    2 + 2
2700}
2701"#,
2702        );
2703    }
2704
2705    #[test]
2706    fn param_from_closure() {
2707        check_assist(
2708            extract_function,
2709            r#"
2710fn main() {
2711    let lambda = |x: u32| $0x * 2$0;
2712}
2713"#,
2714            r#"
2715fn main() {
2716    let lambda = |x: u32| fun_name(x);
2717}
2718
2719fn $0fun_name(x: u32) -> u32 {
2720    x * 2
2721}
2722"#,
2723        );
2724    }
2725
2726    #[test]
2727    fn extract_return_stmt() {
2728        check_assist(
2729            extract_function,
2730            r#"
2731fn foo() -> u32 {
2732    $0return 2 + 2$0;
2733}
2734"#,
2735            r#"
2736fn foo() -> u32 {
2737    return fun_name();
2738}
2739
2740fn $0fun_name() -> u32 {
2741    2 + 2
2742}
2743"#,
2744        );
2745    }
2746
2747    #[test]
2748    fn does_not_add_extra_whitespace() {
2749        check_assist(
2750            extract_function,
2751            r#"
2752fn foo() -> u32 {
2753
2754
2755    $0return 2 + 2$0;
2756}
2757"#,
2758            r#"
2759fn foo() -> u32 {
2760
2761
2762    return fun_name();
2763}
2764
2765fn $0fun_name() -> u32 {
2766    2 + 2
2767}
2768"#,
2769        );
2770    }
2771
2772    #[test]
2773    fn break_stmt() {
2774        check_assist(
2775            extract_function,
2776            r#"
2777fn main() {
2778    let result = loop {
2779        $0break 2 + 2$0;
2780    };
2781}
2782"#,
2783            r#"
2784fn main() {
2785    let result = loop {
2786        break fun_name();
2787    };
2788}
2789
2790fn $0fun_name() -> i32 {
2791    2 + 2
2792}
2793"#,
2794        );
2795    }
2796
2797    #[test]
2798    fn extract_cast() {
2799        check_assist(
2800            extract_function,
2801            r#"
2802fn main() {
2803    let v = $00f32 as u32$0;
2804}
2805"#,
2806            r#"
2807fn main() {
2808    let v = fun_name();
2809}
2810
2811fn $0fun_name() -> u32 {
2812    0f32 as u32
2813}
2814"#,
2815        );
2816    }
2817
2818    #[test]
2819    fn return_not_applicable() {
2820        check_assist_not_applicable(extract_function, r"fn foo() { $0return$0; } ");
2821    }
2822
2823    #[test]
2824    fn method_to_freestanding() {
2825        check_assist(
2826            extract_function,
2827            r#"
2828struct S;
2829
2830impl S {
2831    fn foo(&self) -> i32 {
2832        $01+1$0
2833    }
2834}
2835"#,
2836            r#"
2837struct S;
2838
2839impl S {
2840    fn foo(&self) -> i32 {
2841        fun_name()
2842    }
2843}
2844
2845fn $0fun_name() -> i32 {
2846    1+1
2847}
2848"#,
2849        );
2850    }
2851
2852    #[test]
2853    fn method_with_reference() {
2854        check_assist(
2855            extract_function,
2856            r#"
2857struct S { f: i32 };
2858
2859impl S {
2860    fn foo(&self) -> i32 {
2861        $0self.f+self.f$0
2862    }
2863}
2864"#,
2865            r#"
2866struct S { f: i32 };
2867
2868impl S {
2869    fn foo(&self) -> i32 {
2870        self.fun_name()
2871    }
2872
2873    fn $0fun_name(&self) -> i32 {
2874        self.f+self.f
2875    }
2876}
2877"#,
2878        );
2879    }
2880
2881    #[test]
2882    fn method_with_mut() {
2883        check_assist(
2884            extract_function,
2885            r#"
2886struct S { f: i32 };
2887
2888impl S {
2889    fn foo(&mut self) {
2890        $0self.f += 1;$0
2891    }
2892}
2893"#,
2894            r#"
2895struct S { f: i32 };
2896
2897impl S {
2898    fn foo(&mut self) {
2899        self.fun_name();
2900    }
2901
2902    fn $0fun_name(&mut self) {
2903        self.f += 1;
2904    }
2905}
2906"#,
2907        );
2908    }
2909
2910    #[test]
2911    fn variable_defined_inside_and_used_after_no_ret() {
2912        check_assist(
2913            extract_function,
2914            r#"
2915fn foo() {
2916    let n = 1;
2917    $0let k = n * n;$0
2918    let m = k + 1;
2919}
2920"#,
2921            r#"
2922fn foo() {
2923    let n = 1;
2924    let k = fun_name(n);
2925    let m = k + 1;
2926}
2927
2928fn $0fun_name(n: i32) -> i32 {
2929    let k = n * n;
2930    k
2931}
2932"#,
2933        );
2934    }
2935
2936    #[test]
2937    fn variable_defined_inside_and_used_after_mutably_no_ret() {
2938        check_assist(
2939            extract_function,
2940            r#"
2941fn foo() {
2942    let n = 1;
2943    $0let mut k = n * n;$0
2944    k += 1;
2945}
2946"#,
2947            r#"
2948fn foo() {
2949    let n = 1;
2950    let mut k = fun_name(n);
2951    k += 1;
2952}
2953
2954fn $0fun_name(n: i32) -> i32 {
2955    let mut k = n * n;
2956    k
2957}
2958"#,
2959        );
2960    }
2961
2962    #[test]
2963    fn two_variables_defined_inside_and_used_after_no_ret() {
2964        check_assist(
2965            extract_function,
2966            r#"
2967fn foo() {
2968    let n = 1;
2969    $0let k = n * n;
2970    let m = k + 2;$0
2971    let h = k + m;
2972}
2973"#,
2974            r#"
2975fn foo() {
2976    let n = 1;
2977    let (k, m) = fun_name(n);
2978    let h = k + m;
2979}
2980
2981fn $0fun_name(n: i32) -> (i32, i32) {
2982    let k = n * n;
2983    let m = k + 2;
2984    (k, m)
2985}
2986"#,
2987        );
2988    }
2989
2990    #[test]
2991    fn multi_variables_defined_inside_and_used_after_mutably_no_ret() {
2992        check_assist(
2993            extract_function,
2994            r#"
2995fn foo() {
2996    let n = 1;
2997    $0let mut k = n * n;
2998    let mut m = k + 2;
2999    let mut o = m + 3;
3000    o += 1;$0
3001    k += o;
3002    m = 1;
3003}
3004"#,
3005            r#"
3006fn foo() {
3007    let n = 1;
3008    let (mut k, mut m, o) = fun_name(n);
3009    k += o;
3010    m = 1;
3011}
3012
3013fn $0fun_name(n: i32) -> (i32, i32, i32) {
3014    let mut k = n * n;
3015    let mut m = k + 2;
3016    let mut o = m + 3;
3017    o += 1;
3018    (k, m, o)
3019}
3020"#,
3021        );
3022    }
3023
3024    #[test]
3025    fn nontrivial_patterns_define_variables() {
3026        check_assist(
3027            extract_function,
3028            r#"
3029struct Counter(i32);
3030fn foo() {
3031    $0let Counter(n) = Counter(0);$0
3032    let m = n;
3033}
3034"#,
3035            r#"
3036struct Counter(i32);
3037fn foo() {
3038    let n = fun_name();
3039    let m = n;
3040}
3041
3042fn $0fun_name() -> i32 {
3043    let Counter(n) = Counter(0);
3044    n
3045}
3046"#,
3047        );
3048    }
3049
3050    #[test]
3051    fn struct_with_two_fields_pattern_define_variables() {
3052        check_assist(
3053            extract_function,
3054            r#"
3055struct Counter { n: i32, m: i32 };
3056fn foo() {
3057    $0let Counter { n, m: k } = Counter { n: 1, m: 2 };$0
3058    let h = n + k;
3059}
3060"#,
3061            r#"
3062struct Counter { n: i32, m: i32 };
3063fn foo() {
3064    let (n, k) = fun_name();
3065    let h = n + k;
3066}
3067
3068fn $0fun_name() -> (i32, i32) {
3069    let Counter { n, m: k } = Counter { n: 1, m: 2 };
3070    (n, k)
3071}
3072"#,
3073        );
3074    }
3075
3076    #[test]
3077    fn mut_var_from_outer_scope() {
3078        check_assist(
3079            extract_function,
3080            r#"
3081fn foo() {
3082    let mut n = 1;
3083    $0n += 1;$0
3084    let m = n + 1;
3085}
3086"#,
3087            r#"
3088fn foo() {
3089    let mut n = 1;
3090    fun_name(&mut n);
3091    let m = n + 1;
3092}
3093
3094fn $0fun_name(n: &mut i32) {
3095    *n += 1;
3096}
3097"#,
3098        );
3099    }
3100
3101    #[test]
3102    fn mut_field_from_outer_scope() {
3103        check_assist(
3104            extract_function,
3105            r#"
3106struct C { n: i32 }
3107fn foo() {
3108    let mut c = C { n: 0 };
3109    $0c.n += 1;$0
3110    let m = c.n + 1;
3111}
3112"#,
3113            r#"
3114struct C { n: i32 }
3115fn foo() {
3116    let mut c = C { n: 0 };
3117    fun_name(&mut c);
3118    let m = c.n + 1;
3119}
3120
3121fn $0fun_name(c: &mut C) {
3122    c.n += 1;
3123}
3124"#,
3125        );
3126    }
3127
3128    #[test]
3129    fn mut_nested_field_from_outer_scope() {
3130        check_assist(
3131            extract_function,
3132            r#"
3133struct P { n: i32}
3134struct C { p: P }
3135fn foo() {
3136    let mut c = C { p: P { n: 0 } };
3137    let mut v = C { p: P { n: 0 } };
3138    let u = C { p: P { n: 0 } };
3139    $0c.p.n += u.p.n;
3140    let r = &mut v.p.n;$0
3141    let m = c.p.n + v.p.n + u.p.n;
3142}
3143"#,
3144            r#"
3145struct P { n: i32}
3146struct C { p: P }
3147fn foo() {
3148    let mut c = C { p: P { n: 0 } };
3149    let mut v = C { p: P { n: 0 } };
3150    let u = C { p: P { n: 0 } };
3151    fun_name(&mut c, &mut v, &u);
3152    let m = c.p.n + v.p.n + u.p.n;
3153}
3154
3155fn $0fun_name(c: &mut C, v: &mut C, u: &C) {
3156    c.p.n += u.p.n;
3157    let r = &mut v.p.n;
3158}
3159"#,
3160        );
3161    }
3162
3163    #[test]
3164    fn mut_param_many_usages_stmt() {
3165        check_assist(
3166            extract_function,
3167            r#"
3168fn bar(k: i32) {}
3169trait I: Copy {
3170    fn succ(&self) -> Self;
3171    fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
3172}
3173impl I for i32 {
3174    fn succ(&self) -> Self { *self + 1 }
3175}
3176fn foo() {
3177    let mut n = 1;
3178    $0n += n;
3179    bar(n);
3180    bar(n+1);
3181    bar(n*n);
3182    bar(&n);
3183    n.inc();
3184    let v = &mut n;
3185    *v = v.succ();
3186    n.succ();$0
3187    let m = n + 1;
3188}
3189"#,
3190            r#"
3191fn bar(k: i32) {}
3192trait I: Copy {
3193    fn succ(&self) -> Self;
3194    fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
3195}
3196impl I for i32 {
3197    fn succ(&self) -> Self { *self + 1 }
3198}
3199fn foo() {
3200    let mut n = 1;
3201    fun_name(&mut n);
3202    let m = n + 1;
3203}
3204
3205fn $0fun_name(n: &mut i32) {
3206    *n += *n;
3207    bar(*n);
3208    bar(*n+1);
3209    bar(*n**n);
3210    bar(&*n);
3211    n.inc();
3212    let v = n;
3213    *v = v.succ();
3214    n.succ();
3215}
3216"#,
3217        );
3218    }
3219
3220    #[test]
3221    fn mut_param_many_usages_expr() {
3222        check_assist(
3223            extract_function,
3224            r#"
3225fn bar(k: i32) {}
3226trait I: Copy {
3227    fn succ(&self) -> Self;
3228    fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
3229}
3230impl I for i32 {
3231    fn succ(&self) -> Self { *self + 1 }
3232}
3233fn foo() {
3234    let mut n = 1;
3235    $0{
3236        n += n;
3237        bar(n);
3238        bar(n+1);
3239        bar(n*n);
3240        bar(&n);
3241        n.inc();
3242        let v = &mut n;
3243        *v = v.succ();
3244        n.succ();
3245    }$0
3246    let m = n + 1;
3247}
3248"#,
3249            r#"
3250fn bar(k: i32) {}
3251trait I: Copy {
3252    fn succ(&self) -> Self;
3253    fn inc(&mut self) -> Self { let v = self.succ(); *self = v; v }
3254}
3255impl I for i32 {
3256    fn succ(&self) -> Self { *self + 1 }
3257}
3258fn foo() {
3259    let mut n = 1;
3260    fun_name(&mut n);
3261    let m = n + 1;
3262}
3263
3264fn $0fun_name(n: &mut i32) {
3265    *n += *n;
3266    bar(*n);
3267    bar(*n+1);
3268    bar(*n**n);
3269    bar(&*n);
3270    n.inc();
3271    let v = n;
3272    *v = v.succ();
3273    n.succ();
3274}
3275"#,
3276        );
3277    }
3278
3279    #[test]
3280    fn mut_param_by_value() {
3281        check_assist(
3282            extract_function,
3283            r#"
3284fn foo() {
3285    let mut n = 1;
3286    $0n += 1;$0
3287}
3288"#,
3289            r"
3290fn foo() {
3291    let mut n = 1;
3292    fun_name(n);
3293}
3294
3295fn $0fun_name(mut n: i32) {
3296    n += 1;
3297}
3298",
3299        );
3300    }
3301
3302    #[test]
3303    fn mut_param_because_of_mut_ref() {
3304        check_assist(
3305            extract_function,
3306            r#"
3307fn foo() {
3308    let mut n = 1;
3309    $0let v = &mut n;
3310    *v += 1;$0
3311    let k = n;
3312}
3313"#,
3314            r#"
3315fn foo() {
3316    let mut n = 1;
3317    fun_name(&mut n);
3318    let k = n;
3319}
3320
3321fn $0fun_name(n: &mut i32) {
3322    let v = n;
3323    *v += 1;
3324}
3325"#,
3326        );
3327    }
3328
3329    #[test]
3330    fn mut_param_by_value_because_of_mut_ref() {
3331        check_assist(
3332            extract_function,
3333            r"
3334fn foo() {
3335    let mut n = 1;
3336    $0let v = &mut n;
3337    *v += 1;$0
3338}
3339",
3340            r#"
3341fn foo() {
3342    let mut n = 1;
3343    fun_name(n);
3344}
3345
3346fn $0fun_name(mut n: i32) {
3347    let v = &mut n;
3348    *v += 1;
3349}
3350"#,
3351        );
3352    }
3353
3354    #[test]
3355    fn mut_method_call() {
3356        check_assist(
3357            extract_function,
3358            r#"
3359trait I {
3360    fn inc(&mut self);
3361}
3362impl I for i32 {
3363    fn inc(&mut self) { *self += 1 }
3364}
3365fn foo() {
3366    let mut n = 1;
3367    $0n.inc();$0
3368}
3369"#,
3370            r#"
3371trait I {
3372    fn inc(&mut self);
3373}
3374impl I for i32 {
3375    fn inc(&mut self) { *self += 1 }
3376}
3377fn foo() {
3378    let mut n = 1;
3379    fun_name(n);
3380}
3381
3382fn $0fun_name(mut n: i32) {
3383    n.inc();
3384}
3385"#,
3386        );
3387    }
3388
3389    #[test]
3390    fn shared_method_call() {
3391        check_assist(
3392            extract_function,
3393            r#"
3394trait I {
3395    fn succ(&self);
3396}
3397impl I for i32 {
3398    fn succ(&self) { *self + 1 }
3399}
3400fn foo() {
3401    let mut n = 1;
3402    $0n.succ();$0
3403}
3404"#,
3405            r"
3406trait I {
3407    fn succ(&self);
3408}
3409impl I for i32 {
3410    fn succ(&self) { *self + 1 }
3411}
3412fn foo() {
3413    let mut n = 1;
3414    fun_name(n);
3415}
3416
3417fn $0fun_name(n: i32) {
3418    n.succ();
3419}
3420",
3421        );
3422    }
3423
3424    #[test]
3425    fn mut_method_call_with_other_receiver() {
3426        check_assist(
3427            extract_function,
3428            r#"
3429trait I {
3430    fn inc(&mut self, n: i32);
3431}
3432impl I for i32 {
3433    fn inc(&mut self, n: i32) { *self += n }
3434}
3435fn foo() {
3436    let mut n = 1;
3437    $0let mut m = 2;
3438    m.inc(n);$0
3439}
3440"#,
3441            r"
3442trait I {
3443    fn inc(&mut self, n: i32);
3444}
3445impl I for i32 {
3446    fn inc(&mut self, n: i32) { *self += n }
3447}
3448fn foo() {
3449    let mut n = 1;
3450    fun_name(n);
3451}
3452
3453fn $0fun_name(n: i32) {
3454    let mut m = 2;
3455    m.inc(n);
3456}
3457",
3458        );
3459    }
3460
3461    #[test]
3462    fn non_copy_without_usages_after() {
3463        check_assist(
3464            extract_function,
3465            r#"
3466struct Counter(i32);
3467fn foo() {
3468    let c = Counter(0);
3469    $0let n = c.0;$0
3470}
3471"#,
3472            r"
3473struct Counter(i32);
3474fn foo() {
3475    let c = Counter(0);
3476    fun_name(c);
3477}
3478
3479fn $0fun_name(c: Counter) {
3480    let n = c.0;
3481}
3482",
3483        );
3484    }
3485
3486    #[test]
3487    fn non_copy_used_after() {
3488        check_assist(
3489            extract_function,
3490            r"
3491struct Counter(i32);
3492fn foo() {
3493    let c = Counter(0);
3494    $0let n = c.0;$0
3495    let m = c.0;
3496}
3497",
3498            r#"
3499struct Counter(i32);
3500fn foo() {
3501    let c = Counter(0);
3502    fun_name(&c);
3503    let m = c.0;
3504}
3505
3506fn $0fun_name(c: &Counter) {
3507    let n = c.0;
3508}
3509"#,
3510        );
3511    }
3512
3513    #[test]
3514    fn copy_used_after() {
3515        check_assist(
3516            extract_function,
3517            r#"
3518//- minicore: copy
3519fn foo() {
3520    let n = 0;
3521    $0let m = n;$0
3522    let k = n;
3523}
3524"#,
3525            r#"
3526fn foo() {
3527    let n = 0;
3528    fun_name(n);
3529    let k = n;
3530}
3531
3532fn $0fun_name(n: i32) {
3533    let m = n;
3534}
3535"#,
3536        )
3537    }
3538
3539    #[test]
3540    fn copy_custom_used_after() {
3541        check_assist(
3542            extract_function,
3543            r#"
3544//- minicore: copy, derive
3545#[derive(Clone, Copy)]
3546struct Counter(i32);
3547fn foo() {
3548    let c = Counter(0);
3549    $0let n = c.0;$0
3550    let m = c.0;
3551}
3552"#,
3553            r#"
3554#[derive(Clone, Copy)]
3555struct Counter(i32);
3556fn foo() {
3557    let c = Counter(0);
3558    fun_name(c);
3559    let m = c.0;
3560}
3561
3562fn $0fun_name(c: Counter) {
3563    let n = c.0;
3564}
3565"#,
3566        );
3567    }
3568
3569    #[test]
3570    fn indented_stmts() {
3571        check_assist(
3572            extract_function,
3573            r#"
3574fn foo() {
3575    if true {
3576        loop {
3577            $0let n = 1;
3578            let m = 2;$0
3579        }
3580    }
3581}
3582"#,
3583            r#"
3584fn foo() {
3585    if true {
3586        loop {
3587            fun_name();
3588        }
3589    }
3590}
3591
3592fn $0fun_name() {
3593    let n = 1;
3594    let m = 2;
3595}
3596"#,
3597        );
3598    }
3599
3600    #[test]
3601    fn indented_stmts_inside_mod() {
3602        check_assist(
3603            extract_function,
3604            r#"
3605mod bar {
3606    fn foo() {
3607        if true {
3608            loop {
3609                $0let n = 1;
3610                let m = 2;$0
3611            }
3612        }
3613    }
3614}
3615"#,
3616            r#"
3617mod bar {
3618    fn foo() {
3619        if true {
3620            loop {
3621                fun_name();
3622            }
3623        }
3624    }
3625
3626    fn $0fun_name() {
3627        let n = 1;
3628        let m = 2;
3629    }
3630}
3631"#,
3632        );
3633    }
3634
3635    #[test]
3636    fn break_loop() {
3637        check_assist(
3638            extract_function,
3639            r#"
3640//- minicore: option
3641fn foo() {
3642    loop {
3643        let n = 1;
3644        $0let m = n + 1;
3645        break;
3646        let k = 2;$0
3647        let h = 1 + k;
3648    }
3649}
3650"#,
3651            r#"
3652fn foo() {
3653    loop {
3654        let n = 1;
3655        let k = match fun_name(n) {
3656            Some(value) => value,
3657            None => break,
3658        };
3659        let h = 1 + k;
3660    }
3661}
3662
3663fn $0fun_name(n: i32) -> Option<i32> {
3664    let m = n + 1;
3665    return None;
3666    let k = 2;
3667    Some(k)
3668}
3669"#,
3670        );
3671    }
3672
3673    #[test]
3674    fn return_to_parent() {
3675        check_assist(
3676            extract_function,
3677            r#"
3678//- minicore: copy, result
3679fn foo() -> i64 {
3680    let n = 1;
3681    $0let m = n + 1;
3682    return 1;
3683    let k = 2;$0
3684    (n + k) as i64
3685}
3686"#,
3687            r#"
3688fn foo() -> i64 {
3689    let n = 1;
3690    let k = match fun_name(n) {
3691        Ok(value) => value,
3692        Err(value) => return value,
3693    };
3694    (n + k) as i64
3695}
3696
3697fn $0fun_name(n: i32) -> Result<i32, i64> {
3698    let m = n + 1;
3699    return Err(1);
3700    let k = 2;
3701    Ok(k)
3702}
3703"#,
3704        );
3705    }
3706
3707    #[test]
3708    fn break_and_continue() {
3709        cov_mark::check!(external_control_flow_break_and_continue);
3710        check_assist_not_applicable(
3711            extract_function,
3712            r#"
3713fn foo() {
3714    loop {
3715        let n = 1;
3716        $0let m = n + 1;
3717        break;
3718        let k = 2;
3719        continue;
3720        let k = k + 1;$0
3721        let r = n + k;
3722    }
3723}
3724"#,
3725        );
3726    }
3727
3728    #[test]
3729    fn return_and_break() {
3730        cov_mark::check!(external_control_flow_return_and_bc);
3731        check_assist_not_applicable(
3732            extract_function,
3733            r#"
3734fn foo() {
3735    loop {
3736        let n = 1;
3737        $0let m = n + 1;
3738        break;
3739        let k = 2;
3740        return;
3741        let k = k + 1;$0
3742        let r = n + k;
3743    }
3744}
3745"#,
3746        );
3747    }
3748
3749    #[test]
3750    fn break_loop_with_if() {
3751        check_assist(
3752            extract_function,
3753            r#"
3754//- minicore: try
3755fn foo() {
3756    loop {
3757        let mut n = 1;
3758        $0let m = n + 1;
3759        break;
3760        n += m;$0
3761        let h = 1 + n;
3762    }
3763}
3764"#,
3765            r#"
3766use core::ops::ControlFlow;
3767
3768fn foo() {
3769    loop {
3770        let mut n = 1;
3771        if let ControlFlow::Break(_) = fun_name(&mut n) {
3772            break;
3773        }
3774        let h = 1 + n;
3775    }
3776}
3777
3778fn $0fun_name(n: &mut i32) -> ControlFlow<()> {
3779    let m = *n + 1;
3780    return ControlFlow::Break(());
3781    *n += m;
3782    ControlFlow::Continue(())
3783}
3784"#,
3785        );
3786    }
3787
3788    #[test]
3789    fn break_loop_nested() {
3790        check_assist(
3791            extract_function,
3792            r#"
3793//- minicore: try
3794fn foo() {
3795    loop {
3796        let mut n = 1;
3797        $0let m = n + 1;
3798        if m == 42 {
3799            break;
3800        }$0
3801        let h = 1;
3802    }
3803}
3804"#,
3805            r#"
3806use core::ops::ControlFlow;
3807
3808fn foo() {
3809    loop {
3810        let mut n = 1;
3811        if let ControlFlow::Break(_) = fun_name(n) {
3812            break;
3813        }
3814        let h = 1;
3815    }
3816}
3817
3818fn $0fun_name(n: i32) -> ControlFlow<()> {
3819    let m = n + 1;
3820    if m == 42 {
3821        return ControlFlow::Break(());
3822    }
3823    ControlFlow::Continue(())
3824}
3825"#,
3826        );
3827    }
3828
3829    #[test]
3830    fn break_loop_nested_labeled() {
3831        check_assist(
3832            extract_function,
3833            r#"
3834//- minicore: try
3835fn foo() {
3836    'bar: loop {
3837        loop {
3838            $0break 'bar;$0
3839        }
3840    }
3841}
3842"#,
3843            r#"
3844use core::ops::ControlFlow;
3845
3846fn foo() {
3847    'bar: loop {
3848        loop {
3849            if let ControlFlow::Break(_) = fun_name() {
3850                break 'bar;
3851            }
3852        }
3853    }
3854}
3855
3856fn $0fun_name() -> ControlFlow<()> {
3857    return ControlFlow::Break(());
3858    ControlFlow::Continue(())
3859}
3860"#,
3861        );
3862    }
3863
3864    #[test]
3865    fn continue_loop_nested_labeled() {
3866        check_assist(
3867            extract_function,
3868            r#"
3869//- minicore: try
3870fn foo() {
3871    'bar: loop {
3872        loop {
3873            $0continue 'bar;$0
3874        }
3875    }
3876}
3877"#,
3878            r#"
3879use core::ops::ControlFlow;
3880
3881fn foo() {
3882    'bar: loop {
3883        loop {
3884            if let ControlFlow::Break(_) = fun_name() {
3885                continue 'bar;
3886            }
3887        }
3888    }
3889}
3890
3891fn $0fun_name() -> ControlFlow<()> {
3892    return ControlFlow::Break(());
3893    ControlFlow::Continue(())
3894}
3895"#,
3896        );
3897    }
3898
3899    #[test]
3900    fn return_from_nested_loop() {
3901        check_assist(
3902            extract_function,
3903            r#"
3904fn foo() {
3905    loop {
3906        let n = 1;$0
3907        let k = 1;
3908        loop {
3909            return;
3910        }
3911        let m = k + 1;$0
3912        let h = 1 + m;
3913    }
3914}
3915"#,
3916            r#"
3917fn foo() {
3918    loop {
3919        let n = 1;
3920        let m = match fun_name() {
3921            Some(value) => value,
3922            None => return,
3923        };
3924        let h = 1 + m;
3925    }
3926}
3927
3928fn $0fun_name() -> Option<i32> {
3929    let k = 1;
3930    loop {
3931        return None;
3932    }
3933    let m = k + 1;
3934    Some(m)
3935}
3936"#,
3937        );
3938    }
3939
3940    #[test]
3941    fn break_from_nested_loop() {
3942        check_assist(
3943            extract_function,
3944            r#"
3945fn foo() {
3946    loop {
3947        let n = 1;
3948        $0let k = 1;
3949        loop {
3950            break;
3951        }
3952        let m = k + 1;$0
3953        let h = 1 + m;
3954    }
3955}
3956"#,
3957            r#"
3958fn foo() {
3959    loop {
3960        let n = 1;
3961        let m = fun_name();
3962        let h = 1 + m;
3963    }
3964}
3965
3966fn $0fun_name() -> i32 {
3967    let k = 1;
3968    loop {
3969        break;
3970    }
3971    let m = k + 1;
3972    m
3973}
3974"#,
3975        );
3976    }
3977
3978    #[test]
3979    fn break_from_nested_and_outer_loops() {
3980        check_assist(
3981            extract_function,
3982            r#"
3983fn foo() {
3984    loop {
3985        let n = 1;
3986        $0let k = 1;
3987        loop {
3988            break;
3989        }
3990        if k == 42 {
3991            break;
3992        }
3993        let m = k + 1;$0
3994        let h = 1 + m;
3995    }
3996}
3997"#,
3998            r#"
3999fn foo() {
4000    loop {
4001        let n = 1;
4002        let m = match fun_name() {
4003            Some(value) => value,
4004            None => break,
4005        };
4006        let h = 1 + m;
4007    }
4008}
4009
4010fn $0fun_name() -> Option<i32> {
4011    let k = 1;
4012    loop {
4013        break;
4014    }
4015    if k == 42 {
4016        return None;
4017    }
4018    let m = k + 1;
4019    Some(m)
4020}
4021"#,
4022        );
4023    }
4024
4025    #[test]
4026    fn return_from_nested_fn() {
4027        check_assist(
4028            extract_function,
4029            r#"
4030fn foo() {
4031    loop {
4032        let n = 1;
4033        $0let k = 1;
4034        fn test() {
4035            return;
4036        }
4037        let m = k + 1;$0
4038        let h = 1 + m;
4039    }
4040}
4041"#,
4042            r#"
4043fn foo() {
4044    loop {
4045        let n = 1;
4046        let m = fun_name();
4047        let h = 1 + m;
4048    }
4049}
4050
4051fn $0fun_name() -> i32 {
4052    let k = 1;
4053    fn test() {
4054        return;
4055    }
4056    let m = k + 1;
4057    m
4058}
4059"#,
4060        );
4061    }
4062
4063    #[test]
4064    fn break_with_value() {
4065        check_assist(
4066            extract_function,
4067            r#"
4068fn foo() -> i32 {
4069    loop {
4070        let n = 1;
4071        $0let k = 1;
4072        if k == 42 {
4073            break 3;
4074        }
4075        let m = k + 1;$0
4076        let h = 1;
4077    }
4078}
4079"#,
4080            r#"
4081fn foo() -> i32 {
4082    loop {
4083        let n = 1;
4084        if let Some(value) = fun_name() {
4085            break value;
4086        }
4087        let h = 1;
4088    }
4089}
4090
4091fn $0fun_name() -> Option<i32> {
4092    let k = 1;
4093    if k == 42 {
4094        return Some(3);
4095    }
4096    let m = k + 1;
4097    None
4098}
4099"#,
4100        );
4101    }
4102
4103    #[test]
4104    fn break_with_value_and_label() {
4105        check_assist(
4106            extract_function,
4107            r#"
4108fn foo() -> i32 {
4109    'bar: loop {
4110        let n = 1;
4111        $0let k = 1;
4112        if k == 42 {
4113            break 'bar 4;
4114        }
4115        let m = k + 1;$0
4116        let h = 1;
4117    }
4118}
4119"#,
4120            r#"
4121fn foo() -> i32 {
4122    'bar: loop {
4123        let n = 1;
4124        if let Some(value) = fun_name() {
4125            break 'bar value;
4126        }
4127        let h = 1;
4128    }
4129}
4130
4131fn $0fun_name() -> Option<i32> {
4132    let k = 1;
4133    if k == 42 {
4134        return Some(4);
4135    }
4136    let m = k + 1;
4137    None
4138}
4139"#,
4140        );
4141    }
4142
4143    #[test]
4144    fn break_with_value_and_return() {
4145        check_assist(
4146            extract_function,
4147            r#"
4148fn foo() -> i64 {
4149    loop {
4150        let n = 1;$0
4151        let k = 1;
4152        if k == 42 {
4153            break 3;
4154        }
4155        let m = k + 1;$0
4156        let h = 1 + m;
4157    }
4158}
4159"#,
4160            r#"
4161fn foo() -> i64 {
4162    loop {
4163        let n = 1;
4164        let m = match fun_name() {
4165            Ok(value) => value,
4166            Err(value) => break value,
4167        };
4168        let h = 1 + m;
4169    }
4170}
4171
4172fn $0fun_name() -> Result<i32, i64> {
4173    let k = 1;
4174    if k == 42 {
4175        return Err(3);
4176    }
4177    let m = k + 1;
4178    Ok(m)
4179}
4180"#,
4181        );
4182    }
4183
4184    #[test]
4185    fn try_option() {
4186        check_assist(
4187            extract_function,
4188            r#"
4189//- minicore: option, add, builtin_impls
4190fn bar() -> Option<i32> { None }
4191fn foo() -> Option<()> {
4192    let n = bar()?;
4193    $0let k = foo()?;
4194    let m = k + 1;$0
4195    let h = 1 + m;
4196    Some(())
4197}
4198"#,
4199            r#"
4200fn bar() -> Option<i32> { None }
4201fn foo() -> Option<()> {
4202    let n = bar()?;
4203    let m = fun_name()?;
4204    let h = 1 + m;
4205    Some(())
4206}
4207
4208fn $0fun_name() -> Option<i32> {
4209    let k = foo()?;
4210    let m = k + 1;
4211    Some(m)
4212}
4213"#,
4214        );
4215    }
4216
4217    #[test]
4218    fn try_option_unit() {
4219        check_assist(
4220            extract_function,
4221            r#"
4222//- minicore: option
4223fn foo() -> Option<()> {
4224    let n = 1;
4225    $0let k = foo()?;
4226    let m = k + 1;$0
4227    let h = 1 + n;
4228    Some(())
4229}
4230"#,
4231            r#"
4232fn foo() -> Option<()> {
4233    let n = 1;
4234    fun_name()?;
4235    let h = 1 + n;
4236    Some(())
4237}
4238
4239fn $0fun_name() -> Option<()> {
4240    let k = foo()?;
4241    let m = k + 1;
4242    Some(())
4243}
4244"#,
4245        );
4246    }
4247
4248    #[test]
4249    fn try_result() {
4250        check_assist(
4251            extract_function,
4252            r#"
4253//- minicore: result, add, builtin_impls
4254fn foo() -> Result<(), i64> {
4255    let n = 1;
4256    $0let k = foo()?;
4257    let m = k + 1;$0
4258    let h = 1 + m;
4259    Ok(())
4260}
4261"#,
4262            r#"
4263fn foo() -> Result<(), i64> {
4264    let n = 1;
4265    let m = fun_name()?;
4266    let h = 1 + m;
4267    Ok(())
4268}
4269
4270fn $0fun_name() -> Result<i32, i64> {
4271    let k = foo()?;
4272    let m = k + 1;
4273    Ok(m)
4274}
4275"#,
4276        );
4277    }
4278
4279    #[test]
4280    fn try_option_with_return() {
4281        check_assist(
4282            extract_function,
4283            r#"
4284//- minicore: option, add, builtin_impls
4285fn foo() -> Option<()> {
4286    let n = 1;
4287    $0let k = foo()?;
4288    if k == 42 {
4289        return None;
4290    }
4291    let m = k + 1;$0
4292    let h = 1 + m;
4293    Some(())
4294}
4295"#,
4296            r#"
4297fn foo() -> Option<()> {
4298    let n = 1;
4299    let m = fun_name()?;
4300    let h = 1 + m;
4301    Some(())
4302}
4303
4304fn $0fun_name() -> Option<i32> {
4305    let k = foo()?;
4306    if k == 42 {
4307        return None;
4308    }
4309    let m = k + 1;
4310    Some(m)
4311}
4312"#,
4313        );
4314    }
4315
4316    #[test]
4317    fn try_result_with_return() {
4318        check_assist(
4319            extract_function,
4320            r#"
4321//- minicore: result, add, builtin_impls
4322fn foo() -> Result<(), i64> {
4323    let n = 1;
4324    $0let k = foo()?;
4325    if k == 42 {
4326        return Err(1);
4327    }
4328    let m = k + 1;$0
4329    let h = 1 + m;
4330    Ok(())
4331}
4332"#,
4333            r#"
4334fn foo() -> Result<(), i64> {
4335    let n = 1;
4336    let m = fun_name()?;
4337    let h = 1 + m;
4338    Ok(())
4339}
4340
4341fn $0fun_name() -> Result<i32, i64> {
4342    let k = foo()?;
4343    if k == 42 {
4344        return Err(1);
4345    }
4346    let m = k + 1;
4347    Ok(m)
4348}
4349"#,
4350        );
4351    }
4352
4353    #[test]
4354    fn try_and_break() {
4355        cov_mark::check!(external_control_flow_try_and_bc);
4356        check_assist_not_applicable(
4357            extract_function,
4358            r#"
4359//- minicore: option
4360fn foo() -> Option<()> {
4361    loop {
4362        let n = Some(1);
4363        $0let m = n? + 1;
4364        break;
4365        let k = 2;
4366        let k = k + 1;$0
4367        let r = n + k;
4368    }
4369    Some(())
4370}
4371"#,
4372        );
4373    }
4374
4375    #[test]
4376    fn try_and_return_ok() {
4377        check_assist(
4378            extract_function,
4379            r#"
4380//- minicore: result, add, builtin_impls
4381fn foo() -> Result<(), i64> {
4382    let n = 1;
4383    $0let k = foo()?;
4384    if k == 42 {
4385        return Ok(1);
4386    }
4387    let m = k + 1;$0
4388    let h = 1 + m;
4389    Ok(())
4390}
4391"#,
4392            r#"
4393fn foo() -> Result<(), i64> {
4394    let n = 1;
4395    let m = fun_name()?;
4396    let h = 1 + m;
4397    Ok(())
4398}
4399
4400fn $0fun_name() -> Result<i32, i64> {
4401    let k = foo()?;
4402    if k == 42 {
4403        return Ok(1);
4404    }
4405    let m = k + 1;
4406    Ok(m)
4407}
4408"#,
4409        );
4410    }
4411
4412    #[test]
4413    fn param_usage_in_macro() {
4414        check_assist(
4415            extract_function,
4416            r#"
4417macro_rules! m {
4418    ($val:expr) => { $val };
4419}
4420
4421fn foo() {
4422    let n = 1;
4423    $0let k = n * m!(n);$0
4424    let m = k + 1;
4425}
4426"#,
4427            r#"
4428macro_rules! m {
4429    ($val:expr) => { $val };
4430}
4431
4432fn foo() {
4433    let n = 1;
4434    let k = fun_name(n);
4435    let m = k + 1;
4436}
4437
4438fn $0fun_name(n: i32) -> i32 {
4439    let k = n * m!(n);
4440    k
4441}
4442"#,
4443        );
4444    }
4445
4446    #[test]
4447    fn param_usage_in_macro_with_nested_tt() {
4448        check_assist(
4449            extract_function,
4450            r#"
4451macro_rules! m {
4452    ($val:expr) => { $val };
4453}
4454
4455fn foo() {
4456    let n = 1;
4457    let t = 1;
4458    $0let k = n * m!((n) + { t });$0
4459    let m = k + 1;
4460}
4461"#,
4462            r#"
4463macro_rules! m {
4464    ($val:expr) => { $val };
4465}
4466
4467fn foo() {
4468    let n = 1;
4469    let t = 1;
4470    let k = fun_name(n, t);
4471    let m = k + 1;
4472}
4473
4474fn $0fun_name(n: i32, t: i32) -> i32 {
4475    let k = n * m!((n) + { t });
4476    k
4477}
4478"#,
4479        )
4480    }
4481
4482    #[test]
4483    fn param_usage_in_macro_with_nested_tt_2() {
4484        check_assist(
4485            extract_function,
4486            r#"
4487macro_rules! m {
4488    ($val:expr) => { $val };
4489}
4490
4491struct S(i32);
4492impl S {
4493    fn foo(&self) {
4494        let n = 1;
4495        $0let k = n * m!((n) + { self.0 });$0
4496        let m = k + 1;
4497    }
4498}
4499"#,
4500            r#"
4501macro_rules! m {
4502    ($val:expr) => { $val };
4503}
4504
4505struct S(i32);
4506impl S {
4507    fn foo(&self) {
4508        let n = 1;
4509        let k = self.fun_name(n);
4510        let m = k + 1;
4511    }
4512
4513    fn $0fun_name(&self, n: i32) -> i32 {
4514        let k = n * m!((n) + { self.0 });
4515        k
4516    }
4517}
4518"#,
4519        )
4520    }
4521
4522    #[test]
4523    fn extract_with_await() {
4524        check_assist(
4525            extract_function,
4526            r#"
4527//- minicore: future
4528fn main() {
4529    $0some_function().await;$0
4530}
4531
4532async fn some_function() {
4533
4534}
4535"#,
4536            r#"
4537fn main() {
4538    fun_name().await;
4539}
4540
4541async fn $0fun_name() {
4542    some_function().await;
4543}
4544
4545async fn some_function() {
4546
4547}
4548"#,
4549        );
4550    }
4551
4552    #[test]
4553    fn extract_with_await_and_result_not_producing_match_expr() {
4554        check_assist(
4555            extract_function,
4556            r#"
4557//- minicore: future, result
4558async fn foo() -> Result<(), ()> {
4559    $0async {}.await;
4560    Err(())?$0
4561}
4562"#,
4563            r#"
4564async fn foo() -> Result<(), ()> {
4565    fun_name().await
4566}
4567
4568async fn $0fun_name() -> Result<(), ()> {
4569    async {}.await;
4570    Err(())?
4571}
4572"#,
4573        );
4574    }
4575
4576    #[test]
4577    fn extract_with_await_and_result_producing_match_expr() {
4578        check_assist(
4579            extract_function,
4580            r#"
4581//- minicore: future
4582async fn foo() -> i32 {
4583    loop {
4584        let n = 1;$0
4585        let k = async { 1 }.await;
4586        if k == 42 {
4587            break 3;
4588        }
4589        let m = k + 1;$0
4590        let h = 1 + m;
4591    }
4592}
4593"#,
4594            r#"
4595async fn foo() -> i32 {
4596    loop {
4597        let n = 1;
4598        let m = match fun_name().await {
4599            Ok(value) => value,
4600            Err(value) => break value,
4601        };
4602        let h = 1 + m;
4603    }
4604}
4605
4606async fn $0fun_name() -> Result<i32, i32> {
4607    let k = async { 1 }.await;
4608    if k == 42 {
4609        return Err(3);
4610    }
4611    let m = k + 1;
4612    Ok(m)
4613}
4614"#,
4615        );
4616    }
4617
4618    #[test]
4619    fn extract_with_await_in_args() {
4620        check_assist(
4621            extract_function,
4622            r#"
4623//- minicore: future
4624fn main() {
4625    $0function_call("a", some_function().await);$0
4626}
4627
4628async fn some_function() {
4629
4630}
4631"#,
4632            r#"
4633fn main() {
4634    fun_name().await;
4635}
4636
4637async fn $0fun_name() {
4638    function_call("a", some_function().await);
4639}
4640
4641async fn some_function() {
4642
4643}
4644"#,
4645        );
4646    }
4647
4648    #[test]
4649    fn extract_does_not_extract_standalone_blocks() {
4650        check_assist_not_applicable(
4651            extract_function,
4652            r#"
4653fn main() $0{}$0
4654"#,
4655        );
4656    }
4657
4658    #[test]
4659    fn extract_adds_comma_for_match_arm() {
4660        check_assist(
4661            extract_function,
4662            r#"
4663fn main() {
4664    match 6 {
4665        100 => $0{ 100 }$0
4666        _ => 0,
4667    };
4668}
4669"#,
4670            r#"
4671fn main() {
4672    match 6 {
4673        100 => fun_name(),
4674        _ => 0,
4675    };
4676}
4677
4678fn $0fun_name() -> i32 {
4679    100
4680}
4681"#,
4682        );
4683        check_assist(
4684            extract_function,
4685            r#"
4686fn main() {
4687    match 6 {
4688        100 => $0{ 100 }$0,
4689        _ => 0,
4690    };
4691}
4692"#,
4693            r#"
4694fn main() {
4695    match 6 {
4696        100 => fun_name(),
4697        _ => 0,
4698    };
4699}
4700
4701fn $0fun_name() -> i32 {
4702    100
4703}
4704"#,
4705        );
4706
4707        // Makes sure no semicolon is added for unit-valued match arms
4708        check_assist(
4709            extract_function,
4710            r#"
4711fn main() {
4712    match () {
4713        _ => $0()$0,
4714    }
4715}
4716"#,
4717            r#"
4718fn main() {
4719    match () {
4720        _ => fun_name(),
4721    }
4722}
4723
4724fn $0fun_name() {
4725    ()
4726}
4727"#,
4728        )
4729    }
4730
4731    #[test]
4732    fn extract_does_not_tear_comments_apart() {
4733        check_assist(
4734            extract_function,
4735            r#"
4736fn foo() {
4737    /*$0*/
4738    foo();
4739    foo();
4740    /*$0*/
4741}
4742"#,
4743            r#"
4744fn foo() {
4745    fun_name();
4746}
4747
4748fn $0fun_name() {
4749    /**/
4750    foo();
4751    foo();
4752    /**/
4753}
4754"#,
4755        );
4756    }
4757
4758    #[test]
4759    fn extract_does_not_tear_body_apart() {
4760        check_assist(
4761            extract_function,
4762            r#"
4763fn foo() {
4764    $0foo();
4765}$0
4766"#,
4767            r#"
4768fn foo() {
4769    fun_name();
4770}
4771
4772fn $0fun_name() {
4773    foo();
4774}
4775"#,
4776        );
4777    }
4778
4779    #[test]
4780    fn extract_does_not_wrap_res_in_res() {
4781        check_assist(
4782            extract_function,
4783            r#"
4784//- minicore: result, try
4785fn foo() -> Result<(), i64> {
4786    $0Result::<i32, i64>::Ok(0)?;
4787    Ok(())$0
4788}
4789"#,
4790            r#"
4791fn foo() -> Result<(), i64> {
4792    fun_name()
4793}
4794
4795fn $0fun_name() -> Result<(), i64> {
4796    Result::<i32, i64>::Ok(0)?;
4797    Ok(())
4798}
4799"#,
4800        );
4801    }
4802
4803    #[test]
4804    fn extract_knows_const() {
4805        check_assist(
4806            extract_function,
4807            r#"
4808const fn foo() {
4809    $0()$0
4810}
4811"#,
4812            r#"
4813const fn foo() {
4814    fun_name();
4815}
4816
4817const fn $0fun_name() {
4818    ()
4819}
4820"#,
4821        );
4822        check_assist(
4823            extract_function,
4824            r#"
4825const FOO: () = {
4826    $0()$0
4827};
4828"#,
4829            r#"
4830const FOO: () = {
4831    fun_name();
4832};
4833
4834const fn $0fun_name() {
4835    ()
4836}
4837"#,
4838        );
4839    }
4840
4841    #[test]
4842    fn extract_does_not_move_outer_loop_vars() {
4843        check_assist(
4844            extract_function,
4845            r#"
4846//- minicore: iterator
4847fn foo() {
4848    let mut x = 5;
4849    for _ in 0..10 {
4850        $0x += 1;$0
4851    }
4852}
4853"#,
4854            r#"
4855fn foo() {
4856    let mut x = 5;
4857    for _ in 0..10 {
4858        fun_name(&mut x);
4859    }
4860}
4861
4862fn $0fun_name(x: &mut i32) {
4863    *x += 1;
4864}
4865"#,
4866        );
4867        check_assist(
4868            extract_function,
4869            r#"
4870//- minicore: iterator
4871fn foo() {
4872    for _ in 0..10 {
4873        let mut x = 5;
4874        $0x += 1;$0
4875    }
4876}
4877"#,
4878            r#"
4879fn foo() {
4880    for _ in 0..10 {
4881        let mut x = 5;
4882        fun_name(x);
4883    }
4884}
4885
4886fn $0fun_name(mut x: i32) {
4887    x += 1;
4888}
4889"#,
4890        );
4891        check_assist(
4892            extract_function,
4893            r#"
4894//- minicore: iterator
4895fn foo() {
4896    loop {
4897        let mut x = 5;
4898        for _ in 0..10 {
4899            $0x += 1;$0
4900        }
4901    }
4902}
4903"#,
4904            r#"
4905fn foo() {
4906    loop {
4907        let mut x = 5;
4908        for _ in 0..10 {
4909            fun_name(&mut x);
4910        }
4911    }
4912}
4913
4914fn $0fun_name(x: &mut i32) {
4915    *x += 1;
4916}
4917"#,
4918        );
4919    }
4920
4921    // regression test for #9822
4922    #[test]
4923    fn extract_mut_ref_param_has_no_mut_binding_in_loop() {
4924        check_assist(
4925            extract_function,
4926            r#"
4927struct Foo;
4928impl Foo {
4929    fn foo(&mut self) {}
4930}
4931fn foo() {
4932    let mut x = Foo;
4933    while false {
4934        let y = &mut x;
4935        $0y.foo();$0
4936    }
4937    let z = x;
4938}
4939"#,
4940            r#"
4941struct Foo;
4942impl Foo {
4943    fn foo(&mut self) {}
4944}
4945fn foo() {
4946    let mut x = Foo;
4947    while false {
4948        let y = &mut x;
4949        fun_name(y);
4950    }
4951    let z = x;
4952}
4953
4954fn $0fun_name(y: &mut Foo) {
4955    y.foo();
4956}
4957"#,
4958        );
4959    }
4960
4961    #[test]
4962    fn extract_with_macro_arg() {
4963        check_assist(
4964            extract_function,
4965            r#"
4966macro_rules! m {
4967    ($val:expr) => { $val };
4968}
4969fn main() {
4970    let bar = "bar";
4971    $0m!(bar);$0
4972}
4973"#,
4974            r#"
4975macro_rules! m {
4976    ($val:expr) => { $val };
4977}
4978fn main() {
4979    let bar = "bar";
4980    fun_name(bar);
4981}
4982
4983fn $0fun_name(bar: &str) {
4984    m!(bar);
4985}
4986"#,
4987        );
4988    }
4989
4990    #[test]
4991    fn unresolvable_types_default_to_placeholder() {
4992        check_assist(
4993            extract_function,
4994            r#"
4995fn foo() {
4996    let a = __unresolved;
4997    let _ = $0{a}$0;
4998}
4999"#,
5000            r#"
5001fn foo() {
5002    let a = __unresolved;
5003    let _ = fun_name(a);
5004}
5005
5006fn $0fun_name(a: _) -> _ {
5007    a
5008}
5009"#,
5010        );
5011    }
5012
5013    #[test]
5014    fn reference_mutable_param_with_further_usages() {
5015        check_assist(
5016            extract_function,
5017            r#"
5018pub struct Foo {
5019    field: u32,
5020}
5021
5022pub fn testfn(arg: &mut Foo) {
5023    $0arg.field = 8;$0
5024    // Simulating access after the extracted portion
5025    arg.field = 16;
5026}
5027"#,
5028            r#"
5029pub struct Foo {
5030    field: u32,
5031}
5032
5033pub fn testfn(arg: &mut Foo) {
5034    fun_name(arg);
5035    // Simulating access after the extracted portion
5036    arg.field = 16;
5037}
5038
5039fn $0fun_name(arg: &mut Foo) {
5040    arg.field = 8;
5041}
5042"#,
5043        );
5044    }
5045
5046    #[test]
5047    fn reference_mutable_param_without_further_usages() {
5048        check_assist(
5049            extract_function,
5050            r#"
5051pub struct Foo {
5052    field: u32,
5053}
5054
5055pub fn testfn(arg: &mut Foo) {
5056    $0arg.field = 8;$0
5057}
5058"#,
5059            r#"
5060pub struct Foo {
5061    field: u32,
5062}
5063
5064pub fn testfn(arg: &mut Foo) {
5065    fun_name(arg);
5066}
5067
5068fn $0fun_name(arg: &mut Foo) {
5069    arg.field = 8;
5070}
5071"#,
5072        );
5073    }
5074    #[test]
5075    fn does_not_import_control_flow() {
5076        check_assist(
5077            extract_function,
5078            r#"
5079//- minicore: try
5080fn func() {
5081    $0let cf = "I'm ControlFlow";$0
5082}
5083"#,
5084            r#"
5085fn func() {
5086    fun_name();
5087}
5088
5089fn $0fun_name() {
5090    let cf = "I'm ControlFlow";
5091}
5092"#,
5093        );
5094    }
5095
5096    #[test]
5097    fn extract_function_copies_comment_at_start() {
5098        check_assist(
5099            extract_function,
5100            r#"
5101fn func() {
5102    let i = 0;
5103    $0// comment here!
5104    let x = 0;$0
5105}
5106"#,
5107            r#"
5108fn func() {
5109    let i = 0;
5110    fun_name();
5111}
5112
5113fn $0fun_name() {
5114    // comment here!
5115    let x = 0;
5116}
5117"#,
5118        );
5119    }
5120
5121    #[test]
5122    fn extract_function_copies_comment_in_between() {
5123        check_assist(
5124            extract_function,
5125            r#"
5126fn func() {
5127    let i = 0;$0
5128    let a = 0;
5129    // comment here!
5130    let x = 0;$0
5131}
5132"#,
5133            r#"
5134fn func() {
5135    let i = 0;
5136    fun_name();
5137}
5138
5139fn $0fun_name() {
5140    let a = 0;
5141    // comment here!
5142    let x = 0;
5143}
5144"#,
5145        );
5146    }
5147
5148    #[test]
5149    fn extract_function_copies_comment_at_end() {
5150        check_assist(
5151            extract_function,
5152            r#"
5153fn func() {
5154    let i = 0;
5155    $0let x = 0;
5156    // comment here!$0
5157}
5158"#,
5159            r#"
5160fn func() {
5161    let i = 0;
5162    fun_name();
5163}
5164
5165fn $0fun_name() {
5166    let x = 0;
5167    // comment here!
5168}
5169"#,
5170        );
5171    }
5172
5173    #[test]
5174    fn extract_function_copies_comment_indented() {
5175        check_assist(
5176            extract_function,
5177            r#"
5178fn func() {
5179    let i = 0;
5180    $0let x = 0;
5181    while(true) {
5182        // comment here!
5183    }$0
5184}
5185"#,
5186            r#"
5187fn func() {
5188    let i = 0;
5189    fun_name();
5190}
5191
5192fn $0fun_name() {
5193    let x = 0;
5194    while(true) {
5195        // comment here!
5196    }
5197}
5198"#,
5199        );
5200    }
5201
5202    #[test]
5203    fn extract_function_does_preserve_whitespace() {
5204        check_assist(
5205            extract_function,
5206            r#"
5207fn func() {
5208    let i = 0;
5209    $0let a = 0;
5210
5211    let x = 0;$0
5212}
5213"#,
5214            r#"
5215fn func() {
5216    let i = 0;
5217    fun_name();
5218}
5219
5220fn $0fun_name() {
5221    let a = 0;
5222
5223    let x = 0;
5224}
5225"#,
5226        );
5227    }
5228
5229    #[test]
5230    fn extract_function_long_form_comment() {
5231        check_assist(
5232            extract_function,
5233            r#"
5234fn func() {
5235    let i = 0;
5236    $0/* a comment */
5237    let x = 0;$0
5238}
5239"#,
5240            r#"
5241fn func() {
5242    let i = 0;
5243    fun_name();
5244}
5245
5246fn $0fun_name() {
5247    /* a comment */
5248    let x = 0;
5249}
5250"#,
5251        );
5252    }
5253
5254    #[test]
5255    fn it_should_not_generate_duplicate_function_names() {
5256        check_assist(
5257            extract_function,
5258            r#"
5259fn fun_name() {
5260    $0let x = 0;$0
5261}
5262"#,
5263            r#"
5264fn fun_name() {
5265    fun_name1();
5266}
5267
5268fn $0fun_name1() {
5269    let x = 0;
5270}
5271"#,
5272        );
5273    }
5274
5275    #[test]
5276    fn should_increment_suffix_until_it_finds_space() {
5277        check_assist(
5278            extract_function,
5279            r#"
5280fn fun_name1() {
5281    let y = 0;
5282}
5283
5284fn fun_name() {
5285    $0let x = 0;$0
5286}
5287"#,
5288            r#"
5289fn fun_name1() {
5290    let y = 0;
5291}
5292
5293fn fun_name() {
5294    fun_name2();
5295}
5296
5297fn $0fun_name2() {
5298    let x = 0;
5299}
5300"#,
5301        );
5302    }
5303
5304    #[test]
5305    fn extract_method_from_trait_impl() {
5306        check_assist(
5307            extract_function,
5308            r#"
5309struct Struct(i32);
5310trait Trait {
5311    fn bar(&self) -> i32;
5312}
5313
5314impl Trait for Struct {
5315    fn bar(&self) -> i32 {
5316        $0self.0 + 2$0
5317    }
5318}
5319"#,
5320            r#"
5321struct Struct(i32);
5322trait Trait {
5323    fn bar(&self) -> i32;
5324}
5325
5326impl Trait for Struct {
5327    fn bar(&self) -> i32 {
5328        self.fun_name()
5329    }
5330}
5331
5332impl Struct {
5333    fn $0fun_name(&self) -> i32 {
5334        self.0 + 2
5335    }
5336}
5337"#,
5338        );
5339    }
5340
5341    #[test]
5342    fn extract_method_from_trait_with_existing_non_empty_impl_block() {
5343        check_assist(
5344            extract_function,
5345            r#"
5346struct Struct(i32);
5347trait Trait {
5348    fn bar(&self) -> i32;
5349}
5350
5351impl Struct {
5352    fn foo() {}
5353}
5354
5355impl Trait for Struct {
5356    fn bar(&self) -> i32 {
5357        $0self.0 + 2$0
5358    }
5359}
5360"#,
5361            r#"
5362struct Struct(i32);
5363trait Trait {
5364    fn bar(&self) -> i32;
5365}
5366
5367impl Struct {
5368    fn foo() {}
5369
5370    fn $0fun_name(&self) -> i32 {
5371        self.0 + 2
5372    }
5373}
5374
5375impl Trait for Struct {
5376    fn bar(&self) -> i32 {
5377        self.fun_name()
5378    }
5379}
5380"#,
5381        )
5382    }
5383
5384    #[test]
5385    fn extract_function_from_trait_with_existing_non_empty_impl_block() {
5386        check_assist(
5387            extract_function,
5388            r#"
5389struct Struct(i32);
5390trait Trait {
5391    fn bar(&self) -> i32;
5392}
5393
5394impl Struct {
5395    fn foo() {}
5396}
5397
5398impl Trait for Struct {
5399    fn bar(&self) -> i32 {
5400        let three_squared = $03 * 3$0;
5401        self.0 + three_squared
5402    }
5403}
5404"#,
5405            r#"
5406struct Struct(i32);
5407trait Trait {
5408    fn bar(&self) -> i32;
5409}
5410
5411impl Struct {
5412    fn foo() {}
5413}
5414
5415impl Trait for Struct {
5416    fn bar(&self) -> i32 {
5417        let three_squared = fun_name();
5418        self.0 + three_squared
5419    }
5420}
5421
5422fn $0fun_name() -> i32 {
5423    3 * 3
5424}
5425"#,
5426        )
5427    }
5428
5429    #[test]
5430    fn extract_method_from_trait_with_multiple_existing_impl_blocks() {
5431        check_assist(
5432            extract_function,
5433            r#"
5434struct Struct(i32);
5435struct StructBefore(i32);
5436struct StructAfter(i32);
5437trait Trait {
5438    fn bar(&self) -> i32;
5439}
5440
5441impl StructBefore {
5442    fn foo(){}
5443}
5444
5445impl Struct {
5446    fn foo(){}
5447}
5448
5449impl StructAfter {
5450    fn foo(){}
5451}
5452
5453impl Trait for Struct {
5454    fn bar(&self) -> i32 {
5455        $0self.0 + 2$0
5456    }
5457}
5458"#,
5459            r#"
5460struct Struct(i32);
5461struct StructBefore(i32);
5462struct StructAfter(i32);
5463trait Trait {
5464    fn bar(&self) -> i32;
5465}
5466
5467impl StructBefore {
5468    fn foo(){}
5469}
5470
5471impl Struct {
5472    fn foo(){}
5473
5474    fn $0fun_name(&self) -> i32 {
5475        self.0 + 2
5476    }
5477}
5478
5479impl StructAfter {
5480    fn foo(){}
5481}
5482
5483impl Trait for Struct {
5484    fn bar(&self) -> i32 {
5485        self.fun_name()
5486    }
5487}
5488"#,
5489        )
5490    }
5491
5492    #[test]
5493    fn extract_method_from_trait_with_multiple_existing_trait_impl_blocks() {
5494        check_assist(
5495            extract_function,
5496            r#"
5497struct Struct(i32);
5498trait Trait {
5499    fn bar(&self) -> i32;
5500}
5501trait TraitBefore {
5502    fn before(&self) -> i32;
5503}
5504trait TraitAfter {
5505    fn after(&self) -> i32;
5506}
5507
5508impl TraitBefore for Struct {
5509    fn before(&self) -> i32 {
5510        42
5511    }
5512}
5513
5514impl Struct {
5515    fn foo(){}
5516}
5517
5518impl TraitAfter for Struct {
5519    fn after(&self) -> i32 {
5520        42
5521    }
5522}
5523
5524impl Trait for Struct {
5525    fn bar(&self) -> i32 {
5526        $0self.0 + 2$0
5527    }
5528}
5529"#,
5530            r#"
5531struct Struct(i32);
5532trait Trait {
5533    fn bar(&self) -> i32;
5534}
5535trait TraitBefore {
5536    fn before(&self) -> i32;
5537}
5538trait TraitAfter {
5539    fn after(&self) -> i32;
5540}
5541
5542impl TraitBefore for Struct {
5543    fn before(&self) -> i32 {
5544        42
5545    }
5546}
5547
5548impl Struct {
5549    fn foo(){}
5550
5551    fn $0fun_name(&self) -> i32 {
5552        self.0 + 2
5553    }
5554}
5555
5556impl TraitAfter for Struct {
5557    fn after(&self) -> i32 {
5558        42
5559    }
5560}
5561
5562impl Trait for Struct {
5563    fn bar(&self) -> i32 {
5564        self.fun_name()
5565    }
5566}
5567"#,
5568        )
5569    }
5570
5571    #[test]
5572    fn closure_arguments() {
5573        check_assist(
5574            extract_function,
5575            r#"
5576fn parent(factor: i32) {
5577    let v = &[1, 2, 3];
5578
5579    $0v.iter().map(|it| it * factor);$0
5580}
5581"#,
5582            r#"
5583fn parent(factor: i32) {
5584    let v = &[1, 2, 3];
5585
5586    fun_name(factor, v);
5587}
5588
5589fn $0fun_name(factor: i32, v: &[i32; 3]) {
5590    v.iter().map(|it| it * factor);
5591}
5592"#,
5593        );
5594    }
5595
5596    #[test]
5597    fn preserve_generics() {
5598        check_assist(
5599            extract_function,
5600            r#"
5601fn func<T: Debug>(i: T) {
5602    $0foo(i);$0
5603}
5604"#,
5605            r#"
5606fn func<T: Debug>(i: T) {
5607    fun_name(i);
5608}
5609
5610fn $0fun_name<T: Debug>(i: T) {
5611    foo(i);
5612}
5613"#,
5614        );
5615    }
5616
5617    #[test]
5618    fn dont_emit_type_with_hidden_lifetime_parameter() {
5619        // FIXME: We should emit a `<T: Debug>` generic argument for the generated function
5620        check_assist(
5621            extract_function,
5622            r#"
5623struct Struct<'a, T>(&'a T);
5624fn func<T: Debug>(i: Struct<'_, T>) {
5625    $0foo(i);$0
5626}
5627"#,
5628            r#"
5629struct Struct<'a, T>(&'a T);
5630fn func<T: Debug>(i: Struct<'_, T>) {
5631    fun_name(i);
5632}
5633
5634fn $0fun_name(i: Struct<'_, T>) {
5635    foo(i);
5636}
5637"#,
5638        );
5639    }
5640
5641    #[test]
5642    fn preserve_generics_from_body() {
5643        check_assist(
5644            extract_function,
5645            r#"
5646fn func<T: Default>() -> T {
5647    $0T::default()$0
5648}
5649"#,
5650            r#"
5651fn func<T: Default>() -> T {
5652    fun_name()
5653}
5654
5655fn $0fun_name<T: Default>() -> T {
5656    T::default()
5657}
5658"#,
5659        );
5660    }
5661
5662    #[test]
5663    fn filter_unused_generics() {
5664        check_assist(
5665            extract_function,
5666            r#"
5667fn func<T: Debug, U: Copy>(i: T, u: U) {
5668    bar(u);
5669    $0foo(i);$0
5670}
5671"#,
5672            r#"
5673fn func<T: Debug, U: Copy>(i: T, u: U) {
5674    bar(u);
5675    fun_name(i);
5676}
5677
5678fn $0fun_name<T: Debug>(i: T) {
5679    foo(i);
5680}
5681"#,
5682        );
5683    }
5684
5685    #[test]
5686    fn empty_generic_param_list() {
5687        check_assist(
5688            extract_function,
5689            r#"
5690fn func<T: Debug>(t: T, i: u32) {
5691    bar(t);
5692    $0foo(i);$0
5693}
5694"#,
5695            r#"
5696fn func<T: Debug>(t: T, i: u32) {
5697    bar(t);
5698    fun_name(i);
5699}
5700
5701fn $0fun_name(i: u32) {
5702    foo(i);
5703}
5704"#,
5705        );
5706    }
5707
5708    #[test]
5709    fn preserve_where_clause() {
5710        check_assist(
5711            extract_function,
5712            r#"
5713fn func<T>(i: T) where T: Debug {
5714    $0foo(i);$0
5715}
5716"#,
5717            r#"
5718fn func<T>(i: T) where T: Debug {
5719    fun_name(i);
5720}
5721
5722fn $0fun_name<T>(i: T) where T: Debug {
5723    foo(i);
5724}
5725"#,
5726        );
5727    }
5728
5729    #[test]
5730    fn filter_unused_where_clause() {
5731        check_assist(
5732            extract_function,
5733            r#"
5734fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
5735    bar(u);
5736    $0foo(i);$0
5737}
5738"#,
5739            r#"
5740fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
5741    bar(u);
5742    fun_name(i);
5743}
5744
5745fn $0fun_name<T>(i: T) where T: Debug {
5746    foo(i);
5747}
5748"#,
5749        );
5750    }
5751
5752    #[test]
5753    fn nested_generics() {
5754        check_assist(
5755            extract_function,
5756            r#"
5757struct Struct<T: Into<i32>>(T);
5758impl <T: Into<i32> + Copy> Struct<T> {
5759    fn func<V: Into<i32>>(&self, v: V) -> i32 {
5760        let t = self.0;
5761        $0t.into() + v.into()$0
5762    }
5763}
5764"#,
5765            r#"
5766struct Struct<T: Into<i32>>(T);
5767impl <T: Into<i32> + Copy> Struct<T> {
5768    fn func<V: Into<i32>>(&self, v: V) -> i32 {
5769        let t = self.0;
5770        fun_name(v, t)
5771    }
5772}
5773
5774fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(v: V, t: T) -> i32 {
5775    t.into() + v.into()
5776}
5777"#,
5778        );
5779    }
5780
5781    #[test]
5782    fn filters_unused_nested_generics() {
5783        check_assist(
5784            extract_function,
5785            r#"
5786struct Struct<T: Into<i32>, U: Debug>(T, U);
5787impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
5788    fn func<V: Into<i32>>(&self, v: V) -> i32 {
5789        let t = self.0;
5790        $0t.into() + v.into()$0
5791    }
5792}
5793"#,
5794            r#"
5795struct Struct<T: Into<i32>, U: Debug>(T, U);
5796impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
5797    fn func<V: Into<i32>>(&self, v: V) -> i32 {
5798        let t = self.0;
5799        fun_name(v, t)
5800    }
5801}
5802
5803fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(v: V, t: T) -> i32 {
5804    t.into() + v.into()
5805}
5806"#,
5807        );
5808    }
5809
5810    #[test]
5811    fn nested_where_clauses() {
5812        check_assist(
5813            extract_function,
5814            r#"
5815struct Struct<T>(T) where T: Into<i32>;
5816impl <T> Struct<T> where T: Into<i32> + Copy {
5817    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
5818        let t = self.0;
5819        $0t.into() + v.into()$0
5820    }
5821}
5822"#,
5823            r#"
5824struct Struct<T>(T) where T: Into<i32>;
5825impl <T> Struct<T> where T: Into<i32> + Copy {
5826    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
5827        let t = self.0;
5828        fun_name(v, t)
5829    }
5830}
5831
5832fn $0fun_name<T, V>(v: V, t: T) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
5833    t.into() + v.into()
5834}
5835"#,
5836        );
5837    }
5838
5839    #[test]
5840    fn filters_unused_nested_where_clauses() {
5841        check_assist(
5842            extract_function,
5843            r#"
5844struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
5845impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
5846    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
5847        let t = self.0;
5848        $0t.into() + v.into()$0
5849    }
5850}
5851"#,
5852            r#"
5853struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
5854impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
5855    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
5856        let t = self.0;
5857        fun_name(v, t)
5858    }
5859}
5860
5861fn $0fun_name<T, V>(v: V, t: T) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
5862    t.into() + v.into()
5863}
5864"#,
5865        );
5866    }
5867
5868    #[test]
5869    fn tail_expr_no_extra_control_flow() {
5870        check_assist(
5871            extract_function,
5872            r#"
5873//- minicore: result
5874fn fallible() -> Result<(), ()> {
5875    $0if true {
5876        return Err(());
5877    }
5878    Ok(())$0
5879}
5880"#,
5881            r#"
5882fn fallible() -> Result<(), ()> {
5883    fun_name()
5884}
5885
5886fn $0fun_name() -> Result<(), ()> {
5887    if true {
5888        return Err(());
5889    }
5890    Ok(())
5891}
5892"#,
5893        );
5894    }
5895
5896    #[test]
5897    fn non_tail_expr_of_tail_expr_loop() {
5898        check_assist(
5899            extract_function,
5900            r#"
5901pub fn f() {
5902    loop {
5903        $0if true {
5904            continue;
5905        }$0
5906
5907        if false {
5908            break;
5909        }
5910    }
5911}
5912"#,
5913            r#"
5914pub fn f() {
5915    loop {
5916        if let ControlFlow::Break(_) = fun_name() {
5917            continue;
5918        }
5919
5920        if false {
5921            break;
5922        }
5923    }
5924}
5925
5926fn $0fun_name() -> ControlFlow<()> {
5927    if true {
5928        return ControlFlow::Break(());
5929    }
5930    ControlFlow::Continue(())
5931}
5932"#,
5933        );
5934    }
5935
5936    #[test]
5937    fn non_tail_expr_of_tail_if_block() {
5938        // FIXME: double semicolon
5939        check_assist(
5940            extract_function,
5941            r#"
5942//- minicore: option, try
5943fn f() -> Option<()> {
5944    if true {
5945        let a = $0if true {
5946            Some(())?
5947        } else {
5948            ()
5949        }$0;
5950        Some(a)
5951    } else {
5952        None
5953    }
5954}
5955"#,
5956            r#"
5957fn f() -> Option<()> {
5958    if true {
5959        let a = fun_name()?;;
5960        Some(a)
5961    } else {
5962        None
5963    }
5964}
5965
5966fn $0fun_name() -> Option<()> {
5967    Some(if true {
5968        Some(())?
5969    } else {
5970        ()
5971    })
5972}
5973"#,
5974        );
5975    }
5976
5977    #[test]
5978    fn tail_expr_of_tail_block_nested() {
5979        check_assist(
5980            extract_function,
5981            r#"
5982//- minicore: option, try
5983fn f() -> Option<()> {
5984    if true {
5985        $0{
5986            let a = if true {
5987                Some(())?
5988            } else {
5989                ()
5990            };
5991            Some(a)
5992        }$0
5993    } else {
5994        None
5995    }
5996}
5997"#,
5998            r#"
5999fn f() -> Option<()> {
6000    if true {
6001        fun_name()
6002    } else {
6003        None
6004    }
6005}
6006
6007fn $0fun_name() -> Option<()> {
6008    let a = if true {
6009        Some(())?
6010    } else {
6011        ()
6012    };
6013    Some(a)
6014}
6015"#,
6016        );
6017    }
6018
6019    #[test]
6020    fn non_tail_expr_with_comment_of_tail_expr_loop() {
6021        check_assist(
6022            extract_function,
6023            r#"
6024pub fn f() {
6025    loop {
6026        $0// A comment
6027        if true {
6028            continue;
6029        }$0
6030        if false {
6031            break;
6032        }
6033    }
6034}
6035"#,
6036            r#"
6037pub fn f() {
6038    loop {
6039        if let ControlFlow::Break(_) = fun_name() {
6040            continue;
6041        }
6042        if false {
6043            break;
6044        }
6045    }
6046}
6047
6048fn $0fun_name() -> ControlFlow<()> {
6049    // A comment
6050    if true {
6051        return ControlFlow::Break(());
6052    }
6053    ControlFlow::Continue(())
6054}
6055"#,
6056        );
6057    }
6058
6059    #[test]
6060    fn comments_in_block_expr() {
6061        check_assist(
6062            extract_function,
6063            r#"
6064fn f() {
6065    let c = $0{
6066        // comment 1
6067        let a = 2 + 3;
6068        // comment 2
6069        let b = 5;
6070        a + b
6071    }$0;
6072}
6073"#,
6074            r#"
6075fn f() {
6076    let c = fun_name();
6077}
6078
6079fn $0fun_name() -> i32 {
6080    // comment 1
6081    let a = 2 + 3;
6082    // comment 2
6083    let b = 5;
6084    a + b
6085}
6086"#,
6087        );
6088    }
6089
6090    #[test]
6091    fn sort_params_in_order() {
6092        check_assist(
6093            extract_function,
6094            r#"
6095fn existing(a: i32, b: i32, c: i32) {
6096    let x = 32;
6097
6098    let p = $0x + b + c + a$0;
6099}
6100"#,
6101            r#"
6102fn existing(a: i32, b: i32, c: i32) {
6103    let x = 32;
6104
6105    let p = fun_name(a, b, c, x);
6106}
6107
6108fn $0fun_name(a: i32, b: i32, c: i32, x: i32) -> i32 {
6109    x + b + c + a
6110}
6111"#,
6112        );
6113    }
6114
6115    #[test]
6116    fn fmt_macro_argument() {
6117        check_assist(
6118            extract_function,
6119            r#"
6120//- minicore: fmt
6121fn existing(a: i32, b: i32, c: i32) {
6122    $0print!("{a}{}{}", b, "{c}");$0
6123}
6124"#,
6125            r#"
6126fn existing(a: i32, b: i32, c: i32) {
6127    fun_name(a, b);
6128}
6129
6130fn $0fun_name(a: i32, b: i32) {
6131    print!("{a}{}{}", b, "{c}");
6132}
6133"#,
6134        );
6135    }
6136
6137    #[test]
6138    fn in_left_curly_is_not_applicable() {
6139        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6140        check_assist_not_applicable(extract_function, r"fn foo() { $0}$0");
6141    }
6142
6143    #[test]
6144    fn in_right_curly_is_not_applicable() {
6145        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6146        check_assist_not_applicable(extract_function, r"fn foo() $0{$0 }");
6147    }
6148
6149    #[test]
6150    fn in_left_paren_is_not_applicable() {
6151        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6152        check_assist_not_applicable(extract_function, r"fn foo( $0)$0 { }");
6153    }
6154
6155    #[test]
6156    fn in_right_paren_is_not_applicable() {
6157        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6158        check_assist_not_applicable(extract_function, r"fn foo $0($0 ) { }");
6159    }
6160
6161    #[test]
6162    fn in_left_brack_is_not_applicable() {
6163        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6164        check_assist_not_applicable(extract_function, r"fn foo(arr: &mut [i32$0]$0) {}");
6165    }
6166
6167    #[test]
6168    fn in_right_brack_is_not_applicable() {
6169        cov_mark::check!(extract_function_in_braces_is_not_applicable);
6170        check_assist_not_applicable(extract_function, r"fn foo(arr: &mut $0[$0i32]) {}");
6171    }
6172
6173    #[test]
6174    fn issue_20965_panic() {
6175        check_assist(
6176            extract_function,
6177            r#"
6178//- minicore: fmt
6179#[derive(Debug)]
6180struct Foo(&'static str);
6181
6182impl Foo {
6183    fn text(&self) -> &str { self.0 }
6184}
6185
6186fn main() {
6187    let s = Foo("");
6188    $0print!("{}{}", s, s);$0
6189    let _ = s.text() == "";
6190}"#,
6191            r#"
6192#[derive(Debug)]
6193struct Foo(&'static str);
6194
6195impl Foo {
6196    fn text(&self) -> &str { self.0 }
6197}
6198
6199fn main() {
6200    let s = Foo("");
6201    fun_name(&s);
6202    let _ = s.text() == "";
6203}
6204
6205fn $0fun_name(s: &Foo) {
6206    *print!("{}{}", s, s);
6207}"#,
6208        );
6209    }
6210
6211    #[test]
6212    fn parameter_is_added_used_in_eq_expression_in_macro() {
6213        check_assist(
6214            extract_function,
6215            r#"
6216//- minicore: fmt
6217fn foo() {
6218   let v = 123;
6219   $0print!("{v:?}{}", v == 123);$0
6220}"#,
6221            r#"
6222fn foo() {
6223   let v = 123;
6224   fun_name(v);
6225}
6226
6227fn $0fun_name(v: i32) {
6228    print!("{v:?}{}", v == 123);
6229}"#,
6230        );
6231    }
6232
6233    #[test]
6234    fn no_parameter_for_variable_used_only_let_else() {
6235        check_assist(
6236            extract_function,
6237            r#"
6238fn foo() -> u32 {
6239    let x = 5;
6240
6241    $0let Some(y) = Some(1) else {
6242        return x * 2;
6243    };$0
6244
6245    y
6246}"#,
6247            r#"
6248fn foo() -> u32 {
6249    let x = 5;
6250
6251    let y = match fun_name(x) {
6252        Ok(value) => value,
6253        Err(value) => return value,
6254    };
6255
6256    y
6257}
6258
6259fn $0fun_name(x: u32) -> Result<_, u32> {
6260    let Some(y) = Some(1) else {
6261        return Err(x * 2);
6262    };
6263    Ok(y)
6264}"#,
6265        );
6266    }
6267
6268    #[test]
6269    fn deeply_nested_macros() {
6270        check_assist(
6271            extract_function,
6272            r#"
6273macro_rules! m {
6274    ($val:ident) => { $val };
6275}
6276
6277macro_rules! n {
6278    ($v1:ident, $v2:ident) => { m!($v1) + $v2 };
6279}
6280
6281macro_rules! o {
6282    ($v1:ident, $v2:ident, $v3:ident) => { n!($v1, $v2) + $v3 };
6283}
6284
6285fn foo() -> u32 {
6286    let v1 = 1;
6287    let v2 = 2;
6288    $0let v3 = 3;
6289    o!(v1, v2, v3)$0
6290}"#,
6291            r#"
6292macro_rules! m {
6293    ($val:ident) => { $val };
6294}
6295
6296macro_rules! n {
6297    ($v1:ident, $v2:ident) => { m!($v1) + $v2 };
6298}
6299
6300macro_rules! o {
6301    ($v1:ident, $v2:ident, $v3:ident) => { n!($v1, $v2) + $v3 };
6302}
6303
6304fn foo() -> u32 {
6305    let v1 = 1;
6306    let v2 = 2;
6307    fun_name(v1, v2)
6308}
6309
6310fn $0fun_name(v1: u32, v2: u32) -> u32 {
6311    let v3 = 3;
6312    o!(v1, v2, v3)
6313}"#,
6314        );
6315    }
6316
6317    #[test]
6318    fn pattern_assignment() {
6319        check_assist(
6320            extract_function,
6321            r#"
6322struct Point {x: u32, y: u32};
6323
6324fn point() -> Point {
6325    Point { x: 45, y: 50 };
6326}
6327
6328fn foo() {
6329    let mut a = 1;
6330    let mut b = 3;
6331    $0Point { x: a, y: b } = point();$0
6332}
6333"#,
6334            r#"
6335struct Point {x: u32, y: u32};
6336
6337fn point() -> Point {
6338    Point { x: 45, y: 50 };
6339}
6340
6341fn foo() {
6342    let mut a = 1;
6343    let mut b = 3;
6344    fun_name(a, b);
6345}
6346
6347fn $0fun_name(mut a: u32, mut b: u32) {
6348    Point { x: a, y: b } = point();
6349}
6350"#,
6351        );
6352    }
6353
6354    #[test]
6355    fn tuple_assignment() {
6356        check_assist(
6357            extract_function,
6358            r#"
6359fn foo() {
6360    let mut a = 3;
6361    let mut b = 4;
6362    $0(a, b) = (b, a);$0
6363}
6364"#,
6365            r#"
6366fn foo() {
6367    let mut a = 3;
6368    let mut b = 4;
6369    fun_name(a, b);
6370}
6371
6372fn $0fun_name(mut a: i32, mut b: i32) {
6373    (a, b) = (b, a);
6374}
6375"#,
6376        );
6377    }
6378}