Skip to main content

ide_assists/handlers/
extract_function.rs

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