@@ -103,50 +103,49 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
103103
104104 let scope = ImportScope :: find_insert_use_container ( & node, & ctx. sema ) ?;
105105
106+ let outliving_locals: Vec < _ > = ret_values. collect ( ) ;
107+ if stdx:: never!( !outliving_locals. is_empty( ) && !ret_ty. is_unit( ) ) {
108+ // We should not have variables that outlive body if we have expression block
109+ return None ;
110+ }
111+
112+ let params = body. extracted_function_params ( ctx, & container_info, locals_used. iter ( ) . copied ( ) ) ;
113+
114+ let name = make_function_name ( & semantics_scope) ;
115+
116+ let has_impl_wrapper =
117+ insert_after. ancestors ( ) . any ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != insert_after) ;
118+
119+ let fun = Function {
120+ name,
121+ self_param,
122+ params,
123+ control_flow,
124+ ret_ty,
125+ body,
126+ outliving_locals,
127+ contains_tail_expr,
128+ mods : container_info,
129+ } ;
130+
131+ let new_indent = IndentLevel :: from_node ( & insert_after) ;
132+ let old_indent = fun. body . indent_level ( ) ;
133+
134+ let fn_def = match fun. self_param_adt ( ctx) {
135+ Some ( adt) if anchor == Anchor :: Method && !has_impl_wrapper => {
136+ let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ?;
137+ generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
138+ }
139+ _ => format_function ( ctx, module, & fun, old_indent, new_indent) ?,
140+ } ;
141+
106142 acc. add (
107143 AssistId ( "extract_function" , crate :: AssistKind :: RefactorExtract ) ,
108144 "Extract into function" ,
109145 target_range,
110146 move |builder| {
111- let outliving_locals: Vec < _ > = ret_values. collect ( ) ;
112- if stdx:: never!( !outliving_locals. is_empty( ) && !ret_ty. is_unit( ) ) {
113- // We should not have variables that outlive body if we have expression block
114- return ;
115- }
116-
117- let params =
118- body. extracted_function_params ( ctx, & container_info, locals_used. iter ( ) . copied ( ) ) ;
119-
120- let name = make_function_name ( & semantics_scope) ;
121-
122- let fun = Function {
123- name,
124- self_param,
125- params,
126- control_flow,
127- ret_ty,
128- body,
129- outliving_locals,
130- contains_tail_expr,
131- mods : container_info,
132- } ;
133-
134- let new_indent = IndentLevel :: from_node ( & insert_after) ;
135- let old_indent = fun. body . indent_level ( ) ;
136-
137147 builder. replace ( target_range, make_call ( ctx, & fun, old_indent) ) ;
138148
139- let has_impl_wrapper =
140- insert_after. ancestors ( ) . any ( |a| a. kind ( ) == SyntaxKind :: IMPL && a != insert_after) ;
141-
142- let fn_def = match fun. self_param_adt ( ctx) {
143- Some ( adt) if anchor == Anchor :: Method && !has_impl_wrapper => {
144- let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent + 1 ) ;
145- generate_impl_text ( & adt, & fn_def) . replace ( "{\n \n " , "{" )
146- }
147- _ => format_function ( ctx, module, & fun, old_indent, new_indent) ,
148- } ;
149-
150149 if fn_def. contains ( "ControlFlow" ) {
151150 let scope = match scope {
152151 ImportScope :: File ( it) => ImportScope :: File ( builder. make_mut ( it) ) ,
@@ -1501,13 +1500,13 @@ fn format_function(
15011500 fun : & Function ,
15021501 old_indent : IndentLevel ,
15031502 new_indent : IndentLevel ,
1504- ) -> String {
1503+ ) -> Option < String > {
15051504 let mut fn_def = String :: new ( ) ;
15061505
15071506 let fun_name = & fun. name ;
15081507 let params = fun. make_param_list ( ctx, module) ;
15091508 let ret_ty = fun. make_ret_ty ( ctx, module) ;
1510- let body = make_body ( ctx, old_indent, new_indent, fun) ;
1509+ let body = make_body ( ctx, old_indent, new_indent, fun) ? ;
15111510 let const_kw = if fun. mods . is_const { "const " } else { "" } ;
15121511 let async_kw = if fun. control_flow . is_async { "async " } else { "" } ;
15131512 let unsafe_kw = if fun. control_flow . is_unsafe { "unsafe " } else { "" } ;
@@ -1535,7 +1534,7 @@ fn format_function(
15351534
15361535 format_to ! ( fn_def, " {body}" ) ;
15371536
1538- fn_def
1537+ Some ( fn_def)
15391538}
15401539
15411540fn make_generic_params_and_where_clause (
@@ -1721,14 +1720,14 @@ fn make_body(
17211720 old_indent : IndentLevel ,
17221721 new_indent : IndentLevel ,
17231722 fun : & Function ,
1724- ) -> ast:: BlockExpr {
1723+ ) -> Option < ast:: BlockExpr > {
17251724 let ret_ty = fun. return_type ( ctx) ;
17261725 let handler = FlowHandler :: from_ret_ty ( fun, & ret_ty) ;
17271726
17281727 let block = match & fun. body {
17291728 FunctionBody :: Expr ( expr) => {
1730- let expr = rewrite_body_segment ( ctx, & fun. params , & handler, expr. syntax ( ) ) ;
1731- let expr = ast:: Expr :: cast ( expr) . unwrap ( ) ;
1729+ let expr = rewrite_body_segment ( ctx, & fun. params , & handler, expr. syntax ( ) ) ? ;
1730+ let expr = ast:: Expr :: cast ( expr) ? ;
17321731 match expr {
17331732 ast:: Expr :: BlockExpr ( block) => {
17341733 // If the extracted expression is itself a block, there is no need to wrap it inside another block.
@@ -1749,12 +1748,16 @@ fn make_body(
17491748 . children_with_tokens ( )
17501749 . filter ( |it| text_range. contains_range ( it. text_range ( ) ) )
17511750 . map ( |it| match & it {
1752- syntax:: NodeOrToken :: Node ( n) => syntax:: NodeOrToken :: Node (
1753- rewrite_body_segment ( ctx, & fun. params , & handler, n) ,
1754- ) ,
1755- _ => it,
1751+ syntax:: NodeOrToken :: Node ( n) => {
1752+ let bs = rewrite_body_segment ( ctx, & fun. params , & handler, n) ;
1753+ match bs {
1754+ Some ( n) => Some ( syntax:: NodeOrToken :: Node ( n) ) ,
1755+ None => None ,
1756+ }
1757+ }
1758+ _ => Some ( it) ,
17561759 } )
1757- . collect ( ) ;
1760+ . collect :: < Option < _ > > ( ) ? ;
17581761
17591762 let mut tail_expr = match & elements. last ( ) {
17601763 Some ( syntax:: NodeOrToken :: Node ( node) ) if ast:: Expr :: can_cast ( node. kind ( ) ) => {
@@ -1838,7 +1841,7 @@ fn make_body(
18381841 } ) ,
18391842 } ;
18401843
1841- block. indent ( new_indent)
1844+ Some ( block. indent ( new_indent) )
18421845}
18431846
18441847fn map_tail_expr ( block : ast:: BlockExpr , f : impl FnOnce ( ast:: Expr ) -> ast:: Expr ) -> ast:: BlockExpr {
@@ -1896,14 +1899,18 @@ fn rewrite_body_segment(
18961899 params : & [ Param ] ,
18971900 handler : & FlowHandler ,
18981901 syntax : & SyntaxNode ,
1899- ) -> SyntaxNode {
1900- let syntax = fix_param_usages ( ctx, params, syntax) ;
1902+ ) -> Option < SyntaxNode > {
1903+ let syntax = fix_param_usages ( ctx, params, syntax) ? ;
19011904 update_external_control_flow ( handler, & syntax) ;
1902- syntax
1905+ Some ( syntax)
19031906}
19041907
19051908/// change all usages to account for added `&`/`&mut` for some params
1906- fn fix_param_usages ( ctx : & AssistContext < ' _ > , params : & [ Param ] , syntax : & SyntaxNode ) -> SyntaxNode {
1909+ fn fix_param_usages (
1910+ ctx : & AssistContext < ' _ > ,
1911+ params : & [ Param ] ,
1912+ syntax : & SyntaxNode ,
1913+ ) -> Option < SyntaxNode > {
19071914 let mut usages_for_param: Vec < ( & Param , Vec < ast:: Expr > ) > = Vec :: new ( ) ;
19081915
19091916 let tm = TreeMutator :: new ( syntax) ;
@@ -1934,12 +1941,12 @@ fn fix_param_usages(ctx: &AssistContext<'_>, params: &[Param], syntax: &SyntaxNo
19341941 Some ( ast:: Expr :: RefExpr ( node) )
19351942 if param. kind ( ) == ParamKind :: MutRef && node. mut_token ( ) . is_some ( ) =>
19361943 {
1937- ted:: replace ( node. syntax ( ) , node. expr ( ) . unwrap ( ) . syntax ( ) ) ;
1944+ ted:: replace ( node. syntax ( ) , node. expr ( ) ? . syntax ( ) ) ;
19381945 }
19391946 Some ( ast:: Expr :: RefExpr ( node) )
19401947 if param. kind ( ) == ParamKind :: SharedRef && node. mut_token ( ) . is_none ( ) =>
19411948 {
1942- ted:: replace ( node. syntax ( ) , node. expr ( ) . unwrap ( ) . syntax ( ) ) ;
1949+ ted:: replace ( node. syntax ( ) , node. expr ( ) ? . syntax ( ) ) ;
19431950 }
19441951 Some ( _) | None => {
19451952 let p = & make:: expr_prefix ( T ! [ * ] , usage. clone ( ) ) . clone_for_update ( ) ;
@@ -1949,7 +1956,7 @@ fn fix_param_usages(ctx: &AssistContext<'_>, params: &[Param], syntax: &SyntaxNo
19491956 }
19501957 }
19511958
1952- res
1959+ Some ( res)
19531960}
19541961
19551962fn update_external_control_flow ( handler : & FlowHandler , syntax : & SyntaxNode ) {
0 commit comments