@@ -103,50 +103,49 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
103
103
104
104
let scope = ImportScope :: find_insert_use_container ( & node, & ctx. sema ) ?;
105
105
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
+
106
142
acc. add (
107
143
AssistId ( "extract_function" , crate :: AssistKind :: RefactorExtract ) ,
108
144
"Extract into function" ,
109
145
target_range,
110
146
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
-
137
147
builder. replace ( target_range, make_call ( ctx, & fun, old_indent) ) ;
138
148
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
-
150
149
if fn_def. contains ( "ControlFlow" ) {
151
150
let scope = match scope {
152
151
ImportScope :: File ( it) => ImportScope :: File ( builder. make_mut ( it) ) ,
@@ -1501,13 +1500,13 @@ fn format_function(
1501
1500
fun : & Function ,
1502
1501
old_indent : IndentLevel ,
1503
1502
new_indent : IndentLevel ,
1504
- ) -> String {
1503
+ ) -> Option < String > {
1505
1504
let mut fn_def = String :: new ( ) ;
1506
1505
1507
1506
let fun_name = & fun. name ;
1508
1507
let params = fun. make_param_list ( ctx, module) ;
1509
1508
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) ? ;
1511
1510
let const_kw = if fun. mods . is_const { "const " } else { "" } ;
1512
1511
let async_kw = if fun. control_flow . is_async { "async " } else { "" } ;
1513
1512
let unsafe_kw = if fun. control_flow . is_unsafe { "unsafe " } else { "" } ;
@@ -1535,7 +1534,7 @@ fn format_function(
1535
1534
1536
1535
format_to ! ( fn_def, " {body}" ) ;
1537
1536
1538
- fn_def
1537
+ Some ( fn_def)
1539
1538
}
1540
1539
1541
1540
fn make_generic_params_and_where_clause (
@@ -1721,14 +1720,14 @@ fn make_body(
1721
1720
old_indent : IndentLevel ,
1722
1721
new_indent : IndentLevel ,
1723
1722
fun : & Function ,
1724
- ) -> ast:: BlockExpr {
1723
+ ) -> Option < ast:: BlockExpr > {
1725
1724
let ret_ty = fun. return_type ( ctx) ;
1726
1725
let handler = FlowHandler :: from_ret_ty ( fun, & ret_ty) ;
1727
1726
1728
1727
let block = match & fun. body {
1729
1728
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) ? ;
1732
1731
match expr {
1733
1732
ast:: Expr :: BlockExpr ( block) => {
1734
1733
// 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(
1749
1748
. children_with_tokens ( )
1750
1749
. filter ( |it| text_range. contains_range ( it. text_range ( ) ) )
1751
1750
. 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) ,
1756
1759
} )
1757
- . collect ( ) ;
1760
+ . collect :: < Option < _ > > ( ) ? ;
1758
1761
1759
1762
let mut tail_expr = match & elements. last ( ) {
1760
1763
Some ( syntax:: NodeOrToken :: Node ( node) ) if ast:: Expr :: can_cast ( node. kind ( ) ) => {
@@ -1838,7 +1841,7 @@ fn make_body(
1838
1841
} ) ,
1839
1842
} ;
1840
1843
1841
- block. indent ( new_indent)
1844
+ Some ( block. indent ( new_indent) )
1842
1845
}
1843
1846
1844
1847
fn map_tail_expr ( block : ast:: BlockExpr , f : impl FnOnce ( ast:: Expr ) -> ast:: Expr ) -> ast:: BlockExpr {
@@ -1896,14 +1899,18 @@ fn rewrite_body_segment(
1896
1899
params : & [ Param ] ,
1897
1900
handler : & FlowHandler ,
1898
1901
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) ? ;
1901
1904
update_external_control_flow ( handler, & syntax) ;
1902
- syntax
1905
+ Some ( syntax)
1903
1906
}
1904
1907
1905
1908
/// 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 > {
1907
1914
let mut usages_for_param: Vec < ( & Param , Vec < ast:: Expr > ) > = Vec :: new ( ) ;
1908
1915
1909
1916
let tm = TreeMutator :: new ( syntax) ;
@@ -1934,12 +1941,12 @@ fn fix_param_usages(ctx: &AssistContext<'_>, params: &[Param], syntax: &SyntaxNo
1934
1941
Some ( ast:: Expr :: RefExpr ( node) )
1935
1942
if param. kind ( ) == ParamKind :: MutRef && node. mut_token ( ) . is_some ( ) =>
1936
1943
{
1937
- ted:: replace ( node. syntax ( ) , node. expr ( ) . unwrap ( ) . syntax ( ) ) ;
1944
+ ted:: replace ( node. syntax ( ) , node. expr ( ) ? . syntax ( ) ) ;
1938
1945
}
1939
1946
Some ( ast:: Expr :: RefExpr ( node) )
1940
1947
if param. kind ( ) == ParamKind :: SharedRef && node. mut_token ( ) . is_none ( ) =>
1941
1948
{
1942
- ted:: replace ( node. syntax ( ) , node. expr ( ) . unwrap ( ) . syntax ( ) ) ;
1949
+ ted:: replace ( node. syntax ( ) , node. expr ( ) ? . syntax ( ) ) ;
1943
1950
}
1944
1951
Some ( _) | None => {
1945
1952
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
1949
1956
}
1950
1957
}
1951
1958
1952
- res
1959
+ Some ( res)
1953
1960
}
1954
1961
1955
1962
fn update_external_control_flow ( handler : & FlowHandler , syntax : & SyntaxNode ) {
0 commit comments