@@ -103,49 +103,50 @@ 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
-
142
106
acc. add (
143
107
AssistId ( "extract_function" , crate :: AssistKind :: RefactorExtract ) ,
144
108
"Extract into function" ,
145
109
target_range,
146
110
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
+
147
137
builder. replace ( target_range, make_call ( ctx, & fun, old_indent) ) ;
148
138
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
+
149
150
if fn_def. contains ( "ControlFlow" ) {
150
151
let scope = match scope {
151
152
ImportScope :: File ( it) => ImportScope :: File ( builder. make_mut ( it) ) ,
@@ -530,7 +531,7 @@ impl FunctionBody {
530
531
531
532
fn extracted_from_trait_impl ( & self ) -> bool {
532
533
match self . node ( ) . ancestors ( ) . find_map ( ast:: Impl :: cast) {
533
- Some ( c) => return c. trait_ ( ) . is_some ( ) ,
534
+ Some ( c) => c. trait_ ( ) . is_some ( ) ,
534
535
None => false ,
535
536
}
536
537
}
@@ -1047,23 +1048,17 @@ impl GenericParent {
1047
1048
fn generic_parents ( parent : & SyntaxNode ) -> Vec < GenericParent > {
1048
1049
let mut list = Vec :: new ( ) ;
1049
1050
if let Some ( parent_item) = parent. ancestors ( ) . find_map ( ast:: Item :: cast) {
1050
- match parent_item {
1051
- ast:: Item :: Fn ( ref fn_) => {
1052
- if let Some ( parent_parent) = parent_item
1053
- . syntax ( )
1054
- . parent ( )
1055
- . and_then ( |it| it. parent ( ) )
1056
- . and_then ( ast:: Item :: cast)
1057
- {
1058
- match parent_parent {
1059
- ast:: Item :: Impl ( impl_) => list. push ( GenericParent :: Impl ( impl_) ) ,
1060
- ast:: Item :: Trait ( trait_) => list. push ( GenericParent :: Trait ( trait_) ) ,
1061
- _ => ( ) ,
1062
- }
1051
+ if let ast:: Item :: Fn ( ref fn_) = parent_item {
1052
+ if let Some ( parent_parent) =
1053
+ parent_item. syntax ( ) . parent ( ) . and_then ( |it| it. parent ( ) ) . and_then ( ast:: Item :: cast)
1054
+ {
1055
+ match parent_parent {
1056
+ ast:: Item :: Impl ( impl_) => list. push ( GenericParent :: Impl ( impl_) ) ,
1057
+ ast:: Item :: Trait ( trait_) => list. push ( GenericParent :: Trait ( trait_) ) ,
1058
+ _ => ( ) ,
1063
1059
}
1064
- list. push ( GenericParent :: Fn ( fn_. clone ( ) ) ) ;
1065
1060
}
1066
- _ => ( ) ,
1061
+ list . push ( GenericParent :: Fn ( fn_ . clone ( ) ) ) ;
1067
1062
}
1068
1063
}
1069
1064
list
@@ -1500,13 +1495,13 @@ fn format_function(
1500
1495
fun : & Function ,
1501
1496
old_indent : IndentLevel ,
1502
1497
new_indent : IndentLevel ,
1503
- ) -> Option < String > {
1498
+ ) -> String {
1504
1499
let mut fn_def = String :: new ( ) ;
1505
1500
1506
1501
let fun_name = & fun. name ;
1507
1502
let params = fun. make_param_list ( ctx, module) ;
1508
1503
let ret_ty = fun. make_ret_ty ( ctx, module) ;
1509
- let body = make_body ( ctx, old_indent, new_indent, fun) ? ;
1504
+ let body = make_body ( ctx, old_indent, new_indent, fun) ;
1510
1505
let const_kw = if fun. mods . is_const { "const " } else { "" } ;
1511
1506
let async_kw = if fun. control_flow . is_async { "async " } else { "" } ;
1512
1507
let unsafe_kw = if fun. control_flow . is_unsafe { "unsafe " } else { "" } ;
@@ -1534,7 +1529,7 @@ fn format_function(
1534
1529
1535
1530
format_to ! ( fn_def, " {body}" ) ;
1536
1531
1537
- Some ( fn_def)
1532
+ fn_def
1538
1533
}
1539
1534
1540
1535
fn make_generic_params_and_where_clause (
@@ -1720,15 +1715,14 @@ fn make_body(
1720
1715
old_indent : IndentLevel ,
1721
1716
new_indent : IndentLevel ,
1722
1717
fun : & Function ,
1723
- ) -> Option < ast:: BlockExpr > {
1718
+ ) -> ast:: BlockExpr {
1724
1719
let ret_ty = fun. return_type ( ctx) ;
1725
1720
let handler = FlowHandler :: from_ret_ty ( fun, & ret_ty) ;
1726
1721
1727
1722
let block = match & fun. body {
1728
1723
FunctionBody :: Expr ( expr) => {
1729
- let expr = rewrite_body_segment ( ctx, & fun. params , & handler, expr. syntax ( ) )
1730
- . expect ( "rewrite_body_segment failed." ) ;
1731
- let expr = ast:: Expr :: cast ( expr) . expect ( "error while casting body segment to an expr." ) ;
1724
+ let expr = rewrite_body_segment ( ctx, & fun. params , & handler, expr. syntax ( ) ) ;
1725
+ let expr = ast:: Expr :: cast ( expr) . expect ( "Body segment should be an expr" ) ;
1732
1726
match expr {
1733
1727
ast:: Expr :: BlockExpr ( block) => {
1734
1728
// If the extracted expression is itself a block, there is no need to wrap it inside another block.
@@ -1749,16 +1743,12 @@ fn make_body(
1749
1743
. children_with_tokens ( )
1750
1744
. filter ( |it| text_range. contains_range ( it. text_range ( ) ) )
1751
1745
. map ( |it| match & it {
1752
- syntax:: NodeOrToken :: Node ( n) => {
1753
- let bs = rewrite_body_segment ( ctx, & fun. params , & handler, n) ;
1754
- match bs {
1755
- Some ( n) => Some ( syntax:: NodeOrToken :: Node ( n) ) ,
1756
- None => None ,
1757
- }
1758
- }
1759
- _ => Some ( it) ,
1746
+ syntax:: NodeOrToken :: Node ( n) => syntax:: NodeOrToken :: Node (
1747
+ rewrite_body_segment ( ctx, & fun. params , & handler, n) ,
1748
+ ) ,
1749
+ _ => it,
1760
1750
} )
1761
- . collect :: < Option < _ > > ( ) ? ;
1751
+ . collect ( ) ;
1762
1752
1763
1753
let mut tail_expr = match & elements. last ( ) {
1764
1754
Some ( syntax:: NodeOrToken :: Node ( node) ) if ast:: Expr :: can_cast ( node. kind ( ) ) => {
@@ -1842,7 +1832,7 @@ fn make_body(
1842
1832
} ) ,
1843
1833
} ;
1844
1834
1845
- Some ( block. indent ( new_indent) )
1835
+ block. indent ( new_indent)
1846
1836
}
1847
1837
1848
1838
fn map_tail_expr ( block : ast:: BlockExpr , f : impl FnOnce ( ast:: Expr ) -> ast:: Expr ) -> ast:: BlockExpr {
@@ -1872,9 +1862,8 @@ fn with_tail_expr(block: ast::BlockExpr, tail_expr: ast::Expr) -> ast::BlockExpr
1872
1862
1873
1863
if let Some ( stmt_list) = block. stmt_list ( ) {
1874
1864
stmt_list. syntax ( ) . children_with_tokens ( ) . for_each ( |node_or_token| {
1875
- match & node_or_token {
1876
- syntax:: NodeOrToken :: Token ( _) => elements. push ( node_or_token) ,
1877
- _ => ( ) ,
1865
+ if let syntax:: NodeOrToken :: Token ( _) = & node_or_token {
1866
+ elements. push ( node_or_token)
1878
1867
} ;
1879
1868
} ) ;
1880
1869
}
@@ -1900,18 +1889,14 @@ fn rewrite_body_segment(
1900
1889
params : & [ Param ] ,
1901
1890
handler : & FlowHandler ,
1902
1891
syntax : & SyntaxNode ,
1903
- ) -> Option < SyntaxNode > {
1904
- let syntax = fix_param_usages ( ctx, params, syntax) ? ;
1892
+ ) -> SyntaxNode {
1893
+ let syntax = fix_param_usages ( ctx, params, syntax) ;
1905
1894
update_external_control_flow ( handler, & syntax) ;
1906
- Some ( syntax)
1895
+ syntax
1907
1896
}
1908
1897
1909
1898
/// change all usages to account for added `&`/`&mut` for some params
1910
- fn fix_param_usages (
1911
- ctx : & AssistContext < ' _ > ,
1912
- params : & [ Param ] ,
1913
- syntax : & SyntaxNode ,
1914
- ) -> Option < SyntaxNode > {
1899
+ fn fix_param_usages ( ctx : & AssistContext < ' _ > , params : & [ Param ] , syntax : & SyntaxNode ) -> SyntaxNode {
1915
1900
let mut usages_for_param: Vec < ( & Param , Vec < ast:: Expr > ) > = Vec :: new ( ) ;
1916
1901
1917
1902
let tm = TreeMutator :: new ( syntax) ;
@@ -1935,26 +1920,35 @@ fn fix_param_usages(
1935
1920
1936
1921
for ( param, usages) in usages_for_param {
1937
1922
for usage in usages {
1938
- let expr = usage. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: Expr :: cast) ;
1939
- if let Some ( ast:: Expr :: MethodCallExpr ( _) | ast:: Expr :: FieldExpr ( _) ) = expr {
1940
- continue ;
1941
- }
1942
-
1943
- if let Some ( ast:: Expr :: RefExpr ( node) ) = expr {
1944
- if ( param. kind ( ) == ParamKind :: MutRef && node. mut_token ( ) . is_some ( ) )
1945
- || ( param. kind ( ) == ParamKind :: SharedRef && node. mut_token ( ) . is_none ( ) )
1923
+ match usage. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: Expr :: cast) {
1924
+ Some ( ast:: Expr :: MethodCallExpr ( _) | ast:: Expr :: FieldExpr ( _) ) => {
1925
+ // do nothing
1926
+ }
1927
+ Some ( ast:: Expr :: RefExpr ( node) )
1928
+ if param. kind ( ) == ParamKind :: MutRef && node. mut_token ( ) . is_some ( ) =>
1929
+ {
1930
+ ted:: replace (
1931
+ node. syntax ( ) ,
1932
+ node. expr ( ) . expect ( "RefExpr::expr() cannot be None" ) . syntax ( ) ,
1933
+ ) ;
1934
+ }
1935
+ Some ( ast:: Expr :: RefExpr ( node) )
1936
+ if param. kind ( ) == ParamKind :: SharedRef && node. mut_token ( ) . is_none ( ) =>
1946
1937
{
1947
- ted:: replace ( node. syntax ( ) , node. expr ( ) ?. syntax ( ) ) ;
1948
- continue ;
1938
+ ted:: replace (
1939
+ node. syntax ( ) ,
1940
+ node. expr ( ) . expect ( "RefExpr::expr() cannot be None" ) . syntax ( ) ,
1941
+ ) ;
1942
+ }
1943
+ Some ( _) | None => {
1944
+ let p = & make:: expr_prefix ( T ! [ * ] , usage. clone ( ) ) . clone_for_update ( ) ;
1945
+ ted:: replace ( usage. syntax ( ) , p. syntax ( ) )
1949
1946
}
1950
1947
}
1951
-
1952
- let p = & make:: expr_prefix ( T ! [ * ] , usage. clone ( ) ) . clone_for_update ( ) ;
1953
- ted:: replace ( usage. syntax ( ) , p. syntax ( ) )
1954
1948
}
1955
1949
}
1956
1950
1957
- Some ( res)
1951
+ res
1958
1952
}
1959
1953
1960
1954
fn update_external_control_flow ( handler : & FlowHandler , syntax : & SyntaxNode ) {
0 commit comments