Skip to content

Commit a49a0ab

Browse files
committed
Add 'remove this semicolon'
1 parent 0689fdb commit a49a0ab

File tree

2 files changed

+40
-78
lines changed

2 files changed

+40
-78
lines changed

crates/ide_diagnostics/src/handlers/remove_this_semicolon.rs

Lines changed: 0 additions & 76 deletions
This file was deleted.

crates/ide_diagnostics/src/handlers/type_mismatch.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
use hir::{db::AstDatabase, HirDisplay, Type, TypeInfo};
22
use ide_db::{
3-
famous_defs::FamousDefs, source_change::SourceChange,
3+
base_db::{FileLoader, FileRange},
4+
famous_defs::FamousDefs,
5+
source_change::SourceChange,
46
syntax_helpers::node_ext::for_each_tail_expr,
57
};
6-
use syntax::{AstNode, TextRange};
8+
use syntax::{
9+
ast::{BlockExpr, ExprStmt},
10+
AstNode, TextRange, TextSize,
11+
};
712
use text_edit::TextEdit;
813

914
use crate::{fix, Assist, Diagnostic, DiagnosticsContext};
@@ -34,6 +39,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::TypeMismatch) -> Option<Vec<Assi
3439

3540
add_reference(ctx, d, &mut fixes);
3641
add_missing_ok_or_some(ctx, d, &mut fixes);
42+
remove_semicolon(ctx, d, &mut fixes);
3743

3844
if fixes.is_empty() {
3945
None
@@ -110,6 +116,33 @@ fn add_missing_ok_or_some(
110116
Some(())
111117
}
112118

119+
fn remove_semicolon(
120+
ctx: &DiagnosticsContext<'_>,
121+
d: &hir::TypeMismatch,
122+
acc: &mut Vec<Assist>,
123+
) -> Option<()> {
124+
let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
125+
let expr = d.expr.value.to_node(&root);
126+
if !d.actual.is_unit() {
127+
return None;
128+
}
129+
let block = BlockExpr::cast(expr.syntax().clone())?;
130+
let expr_before_semi =
131+
block.statements().last().and_then(|s| ExprStmt::cast(s.syntax().clone()))?;
132+
let type_before_semi = ctx.sema.type_of_expr(&expr_before_semi.expr()?)?.original();
133+
if !type_before_semi.could_coerce_to(ctx.sema.db, &d.expected) {
134+
return None;
135+
}
136+
let semicolon_range = expr_before_semi.semicolon_token()?.text_range();
137+
138+
let edit = TextEdit::delete(semicolon_range);
139+
let source_change =
140+
SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
141+
142+
acc.push(fix("remove_semicolon", "Remove this semicolon", source_change, semicolon_range));
143+
Some(())
144+
}
145+
113146
#[cfg(test)]
114147
mod tests {
115148
use crate::tests::{check_diagnostics, check_fix, check_no_fix};
@@ -437,4 +470,9 @@ fn foo() -> SomeOtherEnum { 0$0 }
437470
"#,
438471
);
439472
}
473+
474+
#[test]
475+
fn remove_semicolon() {
476+
check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
477+
}
440478
}

0 commit comments

Comments
 (0)