1
1
use crate :: { Assist , AssistCtx , AssistId } ;
2
2
3
- use ast:: { BlockExpr , Expr , LoopBodyOwner } ;
3
+ use ast:: { BlockExpr , Expr , ForExpr , IfExpr , LoopBodyOwner , LoopExpr , WhileExpr } ;
4
4
use ra_fmt:: unwrap_trivial_block;
5
- use ra_syntax:: { ast, AstNode , TextRange } ;
5
+ use ra_syntax:: { ast, AstNode , TextRange , T } ;
6
6
7
7
// Assist: unwrap_block
8
8
//
@@ -22,15 +22,11 @@ use ra_syntax::{ast, AstNode, TextRange};
22
22
// }
23
23
// ```
24
24
pub ( crate ) fn unwrap_block ( ctx : AssistCtx ) -> Option < Assist > {
25
- let res = if let Some ( if_expr) = ctx. find_node_at_offset :: < ast:: IfExpr > ( ) {
25
+ let l_curly_token = ctx. find_token_at_offset ( T ! [ '{' ] ) ?;
26
+
27
+ let res = if let Some ( if_expr) = l_curly_token. ancestors ( ) . find_map ( IfExpr :: cast) {
26
28
// if expression
27
- let mut expr_to_unwrap: Option < ast:: Expr > = None ;
28
- for block_expr in if_expr. blocks ( ) {
29
- if let Some ( expr) = excract_expr ( ctx. frange . range , block_expr) {
30
- expr_to_unwrap = Some ( expr) ;
31
- break ;
32
- }
33
- }
29
+ let expr_to_unwrap = if_expr. blocks ( ) . find_map ( |expr| extract_expr ( ctx. frange . range , expr) ) ;
34
30
let expr_to_unwrap = expr_to_unwrap?;
35
31
// Find if we are in a else if block
36
32
let ancestor = if_expr. syntax ( ) . ancestors ( ) . skip ( 1 ) . find_map ( ast:: IfExpr :: cast) ;
@@ -40,20 +36,20 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option<Assist> {
40
36
} else {
41
37
Some ( ( ast:: Expr :: IfExpr ( if_expr) , expr_to_unwrap) )
42
38
}
43
- } else if let Some ( for_expr) = ctx . find_node_at_offset :: < ast :: ForExpr > ( ) {
39
+ } else if let Some ( for_expr) = l_curly_token . ancestors ( ) . find_map ( ForExpr :: cast ) {
44
40
// for expression
45
41
let block_expr = for_expr. loop_body ( ) ?;
46
- excract_expr ( ctx. frange . range , block_expr)
42
+ extract_expr ( ctx. frange . range , block_expr)
47
43
. map ( |expr_to_unwrap| ( ast:: Expr :: ForExpr ( for_expr) , expr_to_unwrap) )
48
- } else if let Some ( while_expr) = ctx . find_node_at_offset :: < ast :: WhileExpr > ( ) {
44
+ } else if let Some ( while_expr) = l_curly_token . ancestors ( ) . find_map ( WhileExpr :: cast ) {
49
45
// while expression
50
46
let block_expr = while_expr. loop_body ( ) ?;
51
- excract_expr ( ctx. frange . range , block_expr)
47
+ extract_expr ( ctx. frange . range , block_expr)
52
48
. map ( |expr_to_unwrap| ( ast:: Expr :: WhileExpr ( while_expr) , expr_to_unwrap) )
53
- } else if let Some ( loop_expr) = ctx . find_node_at_offset :: < ast :: LoopExpr > ( ) {
49
+ } else if let Some ( loop_expr) = l_curly_token . ancestors ( ) . find_map ( LoopExpr :: cast ) {
54
50
// loop expression
55
51
let block_expr = loop_expr. loop_body ( ) ?;
56
- excract_expr ( ctx. frange . range , block_expr)
52
+ extract_expr ( ctx. frange . range , block_expr)
57
53
. map ( |expr_to_unwrap| ( ast:: Expr :: LoopExpr ( loop_expr) , expr_to_unwrap) )
58
54
} else {
59
55
None
@@ -80,7 +76,7 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option<Assist> {
80
76
} )
81
77
}
82
78
83
- fn excract_expr ( cursor_range : TextRange , block_expr : BlockExpr ) -> Option < Expr > {
79
+ fn extract_expr ( cursor_range : TextRange , block_expr : BlockExpr ) -> Option < Expr > {
84
80
let block = block_expr. block ( ) ?;
85
81
let cursor_in_range = block. l_curly_token ( ) ?. text_range ( ) . contains_range ( cursor_range) ;
86
82
@@ -200,65 +196,6 @@ mod tests {
200
196
) ;
201
197
}
202
198
203
- #[ test]
204
- fn issue_example_with_if ( ) {
205
- check_assist (
206
- unwrap_block,
207
- r#"
208
- fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
209
- if let Some(ty) = &ctx.expected_type {<|>
210
- if let Some(Adt::Enum(enum_data)) = ty.as_adt() {
211
- let variants = enum_data.variants(ctx.db);
212
-
213
- let module = if let Some(module) = ctx.scope().module() {
214
- // Compute path from the completion site if available.
215
- module
216
- } else {
217
- // Otherwise fall back to the enum's definition site.
218
- enum_data.module(ctx.db)
219
- };
220
-
221
- for variant in variants {
222
- if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
223
- // Variants with trivial paths are already added by the existing completion logic,
224
- // so we should avoid adding these twice
225
- if path.segments.len() > 1 {
226
- acc.add_enum_variant(ctx, variant, Some(path.to_string()));
227
- }
228
- }
229
- }
230
- }
231
- }
232
- }
233
- "# ,
234
- r#"
235
- fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &Type) {
236
- <|>if let Some(Adt::Enum(enum_data)) = ty.as_adt() {
237
- let variants = enum_data.variants(ctx.db);
238
-
239
- let module = if let Some(module) = ctx.scope().module() {
240
- // Compute path from the completion site if available.
241
- module
242
- } else {
243
- // Otherwise fall back to the enum's definition site.
244
- enum_data.module(ctx.db)
245
- };
246
-
247
- for variant in variants {
248
- if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) {
249
- // Variants with trivial paths are already added by the existing completion logic,
250
- // so we should avoid adding these twice
251
- if path.segments.len() > 1 {
252
- acc.add_enum_variant(ctx, variant, Some(path.to_string()));
253
- }
254
- }
255
- }
256
- }
257
- }
258
- "# ,
259
- ) ;
260
- }
261
-
262
199
#[ test]
263
200
fn simple_for ( ) {
264
201
check_assist (
0 commit comments