@@ -2,10 +2,15 @@ use std::{hash::BuildHasherDefault, iter};
2
2
3
3
use ast:: make;
4
4
use either:: Either ;
5
- use hir:: { HirDisplay , InFile , Local , Semantics , TypeInfo } ;
5
+ use hir:: { HirDisplay , InFile , Local , ModuleDef , Semantics , TypeInfo } ;
6
6
use ide_db:: {
7
7
defs:: { Definition , NameRefClass } ,
8
- helpers:: node_ext:: { preorder_expr, walk_expr, walk_pat, walk_patterns_in_expr} ,
8
+ helpers:: {
9
+ insert_use:: { insert_use, ImportScope } ,
10
+ mod_path_to_ast,
11
+ node_ext:: { preorder_expr, walk_expr, walk_pat, walk_patterns_in_expr} ,
12
+ FamousDefs ,
13
+ } ,
9
14
search:: { FileReference , ReferenceCategory , SearchScope } ,
10
15
RootDatabase ,
11
16
} ;
@@ -86,6 +91,8 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
86
91
87
92
let target_range = body. text_range ( ) ;
88
93
94
+ let scope = ImportScope :: find_insert_use_container_with_macros ( & node, & ctx. sema ) ?;
95
+
89
96
acc. add (
90
97
AssistId ( "extract_function" , crate :: AssistKind :: RefactorExtract ) ,
91
98
"Extract into function" ,
@@ -118,10 +125,34 @@ pub(crate) fn extract_function(acc: &mut Assists, ctx: &AssistContext) -> Option
118
125
119
126
let fn_def = format_function ( ctx, module, & fun, old_indent, new_indent) ;
120
127
let insert_offset = insert_after. text_range ( ) . end ( ) ;
128
+
129
+ if fn_def. contains ( "ControlFlow" ) {
130
+ let scope = match scope {
131
+ ImportScope :: File ( it) => ImportScope :: File ( builder. make_mut ( it) ) ,
132
+ ImportScope :: Module ( it) => ImportScope :: Module ( builder. make_mut ( it) ) ,
133
+ ImportScope :: Block ( it) => ImportScope :: Block ( builder. make_mut ( it) ) ,
134
+ } ;
135
+
136
+ let control_flow_enum =
137
+ FamousDefs ( & ctx. sema , Some ( module. krate ( ) ) ) . core_ops_ControlFlow ( ) ;
138
+
139
+ if let Some ( control_flow_enum) = control_flow_enum {
140
+ let mod_path = module. find_use_path_prefixed (
141
+ ctx. sema . db ,
142
+ ModuleDef :: from ( control_flow_enum) ,
143
+ ctx. config . insert_use . prefix_kind ,
144
+ ) ;
145
+
146
+ if let Some ( mod_path) = mod_path {
147
+ insert_use ( & scope, mod_path_to_ast ( & mod_path) , & ctx. config . insert_use ) ;
148
+ }
149
+ }
150
+ }
151
+
121
152
match ctx. config . snippet_cap {
122
153
Some ( cap) => builder. insert_snippet ( cap, insert_offset, fn_def) ,
123
154
None => builder. insert ( insert_offset, fn_def) ,
124
- }
155
+ } ;
125
156
} ,
126
157
)
127
158
}
@@ -1184,7 +1215,17 @@ impl FlowHandler {
1184
1215
let action = action. make_result_handler ( None ) ;
1185
1216
let stmt = make:: expr_stmt ( action) ;
1186
1217
let block = make:: block_expr ( iter:: once ( stmt. into ( ) ) , None ) ;
1187
- let condition = make:: condition ( call_expr, None ) ;
1218
+ let controlflow_break_path = make:: path_from_text ( "ControlFlow::Break" ) ;
1219
+ let condition = make:: condition (
1220
+ call_expr,
1221
+ Some (
1222
+ make:: tuple_struct_pat (
1223
+ controlflow_break_path,
1224
+ iter:: once ( make:: wildcard_pat ( ) . into ( ) ) ,
1225
+ )
1226
+ . into ( ) ,
1227
+ ) ,
1228
+ ) ;
1188
1229
make:: expr_if ( condition, block, None )
1189
1230
}
1190
1231
FlowHandler :: IfOption { action } => {
@@ -1326,7 +1367,7 @@ impl Function {
1326
1367
. unwrap_or_else ( make:: ty_placeholder) ;
1327
1368
make:: ext:: ty_result ( fun_ty. make_ty ( ctx, module) , handler_ty)
1328
1369
}
1329
- FlowHandler :: If { .. } => make:: ext :: ty_bool ( ) ,
1370
+ FlowHandler :: If { .. } => make:: ty ( "ControlFlow<()>" ) ,
1330
1371
FlowHandler :: IfOption { action } => {
1331
1372
let handler_ty = action
1332
1373
. expr_ty ( ctx)
@@ -1461,8 +1502,11 @@ fn make_body(
1461
1502
} )
1462
1503
}
1463
1504
FlowHandler :: If { .. } => {
1464
- let lit_false = make:: expr_literal ( "false" ) ;
1465
- with_tail_expr ( block, lit_false. into ( ) )
1505
+ let controlflow_continue = make:: expr_call (
1506
+ make:: expr_path ( make:: path_from_text ( "ControlFlow::Continue" ) ) ,
1507
+ make:: arg_list ( iter:: once ( make:: expr_unit ( ) ) ) ,
1508
+ ) ;
1509
+ with_tail_expr ( block, controlflow_continue. into ( ) )
1466
1510
}
1467
1511
FlowHandler :: IfOption { .. } => {
1468
1512
let none = make:: expr_path ( make:: ext:: ident_path ( "None" ) ) ;
@@ -1638,7 +1682,10 @@ fn update_external_control_flow(handler: &FlowHandler, syntax: &SyntaxNode) {
1638
1682
fn make_rewritten_flow ( handler : & FlowHandler , arg_expr : Option < ast:: Expr > ) -> Option < ast:: Expr > {
1639
1683
let value = match handler {
1640
1684
FlowHandler :: None | FlowHandler :: Try { .. } => return None ,
1641
- FlowHandler :: If { .. } => make:: expr_literal ( "true" ) . into ( ) ,
1685
+ FlowHandler :: If { .. } => make:: expr_call (
1686
+ make:: expr_path ( make:: path_from_text ( "ControlFlow::Break" ) ) ,
1687
+ make:: arg_list ( iter:: once ( make:: expr_unit ( ) ) ) ,
1688
+ ) ,
1642
1689
FlowHandler :: IfOption { .. } => {
1643
1690
let expr = arg_expr. unwrap_or_else ( || make:: expr_tuple ( Vec :: new ( ) ) ) ;
1644
1691
let args = make:: arg_list ( iter:: once ( expr) ) ;
@@ -3270,6 +3317,7 @@ fn foo() {
3270
3317
check_assist (
3271
3318
extract_function,
3272
3319
r#"
3320
+ //- minicore: try
3273
3321
fn foo() {
3274
3322
loop {
3275
3323
let mut n = 1;
@@ -3281,21 +3329,23 @@ fn foo() {
3281
3329
}
3282
3330
"# ,
3283
3331
r#"
3332
+ use core::ops::ControlFlow;
3333
+
3284
3334
fn foo() {
3285
3335
loop {
3286
3336
let mut n = 1;
3287
- if fun_name(&mut n) {
3337
+ if let ControlFlow::Break(_) = fun_name(&mut n) {
3288
3338
break;
3289
3339
}
3290
3340
let h = 1 + n;
3291
3341
}
3292
3342
}
3293
3343
3294
- fn $0fun_name(n: &mut i32) -> bool {
3344
+ fn $0fun_name(n: &mut i32) -> ControlFlow<()> {
3295
3345
let m = *n + 1;
3296
- return true ;
3346
+ return ControlFlow::Break(()) ;
3297
3347
*n += m;
3298
- false
3348
+ ControlFlow::Continue(())
3299
3349
}
3300
3350
"# ,
3301
3351
) ;
@@ -3306,6 +3356,7 @@ fn $0fun_name(n: &mut i32) -> bool {
3306
3356
check_assist (
3307
3357
extract_function,
3308
3358
r#"
3359
+ //- minicore: try
3309
3360
fn foo() {
3310
3361
loop {
3311
3362
let mut n = 1;
@@ -3318,22 +3369,24 @@ fn foo() {
3318
3369
}
3319
3370
"# ,
3320
3371
r#"
3372
+ use core::ops::ControlFlow;
3373
+
3321
3374
fn foo() {
3322
3375
loop {
3323
3376
let mut n = 1;
3324
- if fun_name(n) {
3377
+ if let ControlFlow::Break(_) = fun_name(n) {
3325
3378
break;
3326
3379
}
3327
3380
let h = 1;
3328
3381
}
3329
3382
}
3330
3383
3331
- fn $0fun_name(n: i32) -> bool {
3384
+ fn $0fun_name(n: i32) -> ControlFlow<()> {
3332
3385
let m = n + 1;
3333
3386
if m == 42 {
3334
- return true ;
3387
+ return ControlFlow::Break(()) ;
3335
3388
}
3336
- false
3389
+ ControlFlow::Continue(())
3337
3390
}
3338
3391
"# ,
3339
3392
) ;
0 commit comments