Skip to content

Commit c1fa583

Browse files
bors[bot]matklad
andauthored
Merge #10425
10425: fix: remove semicolon diagnostics only highlights the semi r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 59c758d + 76e8755 commit c1fa583

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

crates/ide_diagnostics/src/handlers/remove_this_semicolon.rs

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
use hir::db::AstDatabase;
2-
use ide_db::source_change::SourceChange;
3-
use syntax::{ast, AstNode};
1+
use ide_db::{
2+
base_db::{FileLoader, FileRange},
3+
source_change::SourceChange,
4+
};
5+
use syntax::{TextRange, TextSize};
46
use text_edit::TextEdit;
57

68
use crate::{fix, Assist, Diagnostic, DiagnosticsContext};
@@ -15,29 +17,42 @@ pub(crate) fn remove_this_semicolon(
1517
Diagnostic::new(
1618
"remove-this-semicolon",
1719
"remove this semicolon",
18-
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
20+
semicolon_range(ctx, d).unwrap_or_else(|it| it).range,
1921
)
2022
.with_fixes(fixes(ctx, d))
2123
}
2224

25+
fn semicolon_range(
26+
ctx: &DiagnosticsContext<'_>,
27+
d: &hir::RemoveThisSemicolon,
28+
) -> Result<FileRange, FileRange> {
29+
let expr_range = ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into()));
30+
let file_text = ctx.sema.db.file_text(expr_range.file_id);
31+
let range_end: usize = expr_range.range.end().into();
32+
// FIXME: This doesn't handle whitespace and comments, but handling those in
33+
// the presence of macros might prove tricky...
34+
if file_text[range_end..].starts_with(';') {
35+
Ok(FileRange {
36+
file_id: expr_range.file_id,
37+
range: TextRange::at(expr_range.range.end(), TextSize::of(';')),
38+
})
39+
} else {
40+
Err(expr_range)
41+
}
42+
}
43+
2344
fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::RemoveThisSemicolon) -> Option<Vec<Assist>> {
24-
let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
25-
26-
let semicolon = d
27-
.expr
28-
.value
29-
.to_node(&root)
30-
.syntax()
31-
.parent()
32-
.and_then(ast::ExprStmt::cast)
33-
.and_then(|expr| expr.semicolon_token())?
34-
.text_range();
35-
36-
let edit = TextEdit::delete(semicolon);
37-
let source_change =
38-
SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
39-
40-
Some(vec![fix("remove_semicolon", "Remove this semicolon", source_change, semicolon)])
45+
let semicolon_range = semicolon_range(ctx, d).ok()?;
46+
47+
let edit = TextEdit::delete(semicolon_range.range);
48+
let source_change = SourceChange::from_text_edit(semicolon_range.file_id, edit);
49+
50+
Some(vec![fix(
51+
"remove_semicolon",
52+
"Remove this semicolon",
53+
source_change,
54+
semicolon_range.range,
55+
)])
4156
}
4257

4358
#[cfg(test)]
@@ -49,7 +64,7 @@ mod tests {
4964
check_diagnostics(
5065
r#"
5166
fn test() -> i32 { 123; }
52-
//^^^ 💡 error: remove this semicolon
67+
//^ 💡 error: remove this semicolon
5368
"#,
5469
);
5570
}

0 commit comments

Comments
 (0)