Skip to content

Commit eea2173

Browse files
committed
Add unwrap block assist #4156
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
1 parent df7899e commit eea2173

File tree

1 file changed

+13
-76
lines changed

1 file changed

+13
-76
lines changed

crates/ra_assists/src/handlers/unwrap_block.rs

Lines changed: 13 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::{Assist, AssistCtx, AssistId};
22

3-
use ast::{BlockExpr, Expr, LoopBodyOwner};
3+
use ast::{BlockExpr, Expr, ForExpr, IfExpr, LoopBodyOwner, LoopExpr, WhileExpr};
44
use ra_fmt::unwrap_trivial_block;
5-
use ra_syntax::{ast, AstNode, TextRange};
5+
use ra_syntax::{ast, AstNode, TextRange, T};
66

77
// Assist: unwrap_block
88
//
@@ -22,15 +22,11 @@ use ra_syntax::{ast, AstNode, TextRange};
2222
// }
2323
// ```
2424
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) {
2628
// 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));
3430
let expr_to_unwrap = expr_to_unwrap?;
3531
// Find if we are in a else if block
3632
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> {
4036
} else {
4137
Some((ast::Expr::IfExpr(if_expr), expr_to_unwrap))
4238
}
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) {
4440
// for expression
4541
let block_expr = for_expr.loop_body()?;
46-
excract_expr(ctx.frange.range, block_expr)
42+
extract_expr(ctx.frange.range, block_expr)
4743
.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) {
4945
// while expression
5046
let block_expr = while_expr.loop_body()?;
51-
excract_expr(ctx.frange.range, block_expr)
47+
extract_expr(ctx.frange.range, block_expr)
5248
.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) {
5450
// loop expression
5551
let block_expr = loop_expr.loop_body()?;
56-
excract_expr(ctx.frange.range, block_expr)
52+
extract_expr(ctx.frange.range, block_expr)
5753
.map(|expr_to_unwrap| (ast::Expr::LoopExpr(loop_expr), expr_to_unwrap))
5854
} else {
5955
None
@@ -80,7 +76,7 @@ pub(crate) fn unwrap_block(ctx: AssistCtx) -> Option<Assist> {
8076
})
8177
}
8278

83-
fn excract_expr(cursor_range: TextRange, block_expr: BlockExpr) -> Option<Expr> {
79+
fn extract_expr(cursor_range: TextRange, block_expr: BlockExpr) -> Option<Expr> {
8480
let block = block_expr.block()?;
8581
let cursor_in_range = block.l_curly_token()?.text_range().contains_range(cursor_range);
8682

@@ -200,65 +196,6 @@ mod tests {
200196
);
201197
}
202198

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-
262199
#[test]
263200
fn simple_for() {
264201
check_assist(

0 commit comments

Comments
 (0)