Skip to content

Commit

Permalink
Stop inserting semicolon when extracting match arm
Browse files Browse the repository at this point in the history
# Overview

Extracting a match arm value that has type unit into a function, when a
comma already follows the match arm value, results in an invalid (syntax
error) semicolon added between the newly generated function's generated
call and the comma.

# Example

Running this extraction

```rust
fn main() {
    match () {
        _ => $0()$0,
    };
}
```

would lead to

```rust
fn main() {
    match () {
        _ => fun_name();,
    };
}

fn fun_name() {
}
```

# Issue / Fix details

This happens because when there is no comma, rust-analyzer would simply
add the comma and wouldn't even try to evaluate whether it needs to add
a semicolon. But when the comma is there, it proceeds to evaluate
whether it needs to add a semicolon and it looks like the evaluation
logic erroneously ignores the possibility that we're in a match arm.
IIUC it never makes sense to add a semicolon when we're extracting from
a match arm value, so I've adjusted the logic to always decide against
adding a semicolon when we're in a match arm
  • Loading branch information
omertuc committed Jul 8, 2023
1 parent db0add1 commit 5e98920
Showing 1 changed file with 30 additions and 6 deletions.
36 changes: 30 additions & 6 deletions crates/ide-assists/src/handlers/extract_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1360,14 +1360,15 @@ fn make_call(ctx: &AssistContext<'_>, fun: &Function, indent: IndentLevel) -> St
}

format_to!(buf, "{expr}");
let insert_comma = fun
.body
.parent()
.and_then(ast::MatchArm::cast)
.map_or(false, |it| it.comma_token().is_none());
let parent_match_arm = fun.body.parent().and_then(ast::MatchArm::cast);
let insert_comma = parent_match_arm.clone().map_or(false, |it| it.comma_token().is_none());

if insert_comma {
buf.push(',');
} else if fun.ret_ty.is_unit() && (!fun.outliving_locals.is_empty() || !expr.is_block_like()) {
} else if parent_match_arm.is_none()
&& fun.ret_ty.is_unit()
&& (!fun.outliving_locals.is_empty() || !expr.is_block_like())
{
buf.push(';');
}
buf
Expand Down Expand Up @@ -4611,6 +4612,29 @@ fn $0fun_name() -> i32 {
}
"#,
);

// Makes sure no semicolon is added for unit-valued match arms
check_assist(
extract_function,
r#"
fn main() {
match () {
_ => $0()$0,
}
}
"#,
r#"
fn main() {
match () {
_ => fun_name(),
}
}
fn $0fun_name() {
()
}
"#,
)
}

#[test]
Expand Down

0 comments on commit 5e98920

Please sign in to comment.