Skip to content

Commit 74f3cca

Browse files
committed
internal: refactor remove this semicolon diagnostics
1 parent 8d391ec commit 74f3cca

File tree

8 files changed

+71
-83
lines changed

8 files changed

+71
-83
lines changed

crates/hir/src/diagnostics.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ diagnostics![
3939
MissingFields,
4040
MissingUnsafe,
4141
NoSuchField,
42+
RemoveThisSemicolon,
4243
UnimplementedBuiltinMacro,
4344
UnresolvedExternCrate,
4445
UnresolvedImport,
@@ -153,26 +154,7 @@ pub struct MismatchedArgCount {
153154

154155
#[derive(Debug)]
155156
pub struct RemoveThisSemicolon {
156-
pub file: HirFileId,
157-
pub expr: AstPtr<ast::Expr>,
158-
}
159-
160-
impl Diagnostic for RemoveThisSemicolon {
161-
fn code(&self) -> DiagnosticCode {
162-
DiagnosticCode("remove-this-semicolon")
163-
}
164-
165-
fn message(&self) -> String {
166-
"Remove this semicolon".to_string()
167-
}
168-
169-
fn display_source(&self) -> InFile<SyntaxNodePtr> {
170-
InFile { file_id: self.file, value: self.expr.clone().into() }
171-
}
172-
173-
fn as_any(&self) -> &(dyn Any + Send + 'static) {
174-
self
175-
}
157+
pub expr: InFile<AstPtr<ast::Expr>>,
176158
}
177159

178160
// Diagnostic: missing-ok-or-some-in-tail-expr

crates/hir/src/lib.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,10 +1184,7 @@ impl Function {
11841184
}
11851185
BodyValidationDiagnostic::RemoveThisSemicolon { expr } => {
11861186
match source_map.expr_syntax(expr) {
1187-
Ok(source_ptr) => sink.push(RemoveThisSemicolon {
1188-
file: source_ptr.file_id,
1189-
expr: source_ptr.value,
1190-
}),
1187+
Ok(expr) => acc.push(RemoveThisSemicolon { expr }.into()),
11911188
Err(SyntheticSyntax) => (),
11921189
}
11931190
}

crates/ide/src/diagnostics.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod mismatched_arg_count;
1111
mod missing_fields;
1212
mod missing_unsafe;
1313
mod no_such_field;
14+
mod remove_this_semicolon;
1415
mod unimplemented_builtin_macro;
1516
mod unresolved_extern_crate;
1617
mod unresolved_import;
@@ -165,9 +166,6 @@ pub(crate) fn diagnostics(
165166
.on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| {
166167
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
167168
})
168-
.on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| {
169-
res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
170-
})
171169
.on::<hir::diagnostics::IncorrectCase, _>(|d| {
172170
res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
173171
})
@@ -223,10 +221,11 @@ pub(crate) fn diagnostics(
223221
let d = match diag {
224222
AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
225223
AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
224+
AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
226225
AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
227226
AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
228-
AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
229227
AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
228+
AnyDiagnostic::RemoveThisSemicolon(d) => remove_this_semicolon::remove_this_semicolon(&ctx, &d),
230229
AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
231230
AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
232231
AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
@@ -838,16 +837,6 @@ fn x(a: S) {
838837
)
839838
}
840839

841-
#[test]
842-
fn missing_semicolon() {
843-
check_diagnostics(
844-
r#"
845-
fn test() -> i32 { 123; }
846-
//^^^ Remove this semicolon
847-
"#,
848-
);
849-
}
850-
851840
#[test]
852841
fn import_extern_crate_clash_with_inner_item() {
853842
// This is more of a resolver test, but doesn't really work with the hir_def testsuite.

crates/ide/src/diagnostics/fixes.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
//! Provides a way to attach fixes to the diagnostics.
22
//! The same module also has all curret custom fixes for the diagnostics implemented.
33
mod change_case;
4-
mod create_field;
5-
mod remove_semicolon;
64
mod replace_with_find_map;
75
mod wrap_tail_expr;
86

crates/ide/src/diagnostics/fixes/create_field.rs

Lines changed: 0 additions & 1 deletion
This file was deleted.

crates/ide/src/diagnostics/fixes/remove_semicolon.rs

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

crates/ide/src/diagnostics/no_such_field.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
pub(super) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic {
1818
Diagnostic::new(
1919
"no-such-field",
20-
"no such field".to_string(),
20+
"no such field",
2121
ctx.sema.diagnostics_display_range(d.field.clone().map(|it| it.into())).range,
2222
)
2323
.with_fixes(fixes(ctx, d))
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use hir::db::AstDatabase;
2+
use ide_db::source_change::SourceChange;
3+
use syntax::{ast, AstNode};
4+
use text_edit::TextEdit;
5+
6+
use crate::{
7+
diagnostics::{fix, Diagnostic, DiagnosticsContext},
8+
Assist,
9+
};
10+
11+
// Diagnostic: remove-this-semicolon
12+
//
13+
// This diagnostic is triggered when there's an erroneous `;` at the end of the block.
14+
pub(super) fn remove_this_semicolon(
15+
ctx: &DiagnosticsContext<'_>,
16+
d: &hir::RemoveThisSemicolon,
17+
) -> Diagnostic {
18+
Diagnostic::new(
19+
"remove-this-semicolon",
20+
"remove this semicolon",
21+
ctx.sema.diagnostics_display_range(d.expr.clone().map(|it| it.into())).range,
22+
)
23+
.with_fixes(fixes(ctx, d))
24+
}
25+
26+
fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::RemoveThisSemicolon) -> Option<Vec<Assist>> {
27+
let root = ctx.sema.db.parse_or_expand(d.expr.file_id)?;
28+
29+
let semicolon = d
30+
.expr
31+
.value
32+
.to_node(&root)
33+
.syntax()
34+
.parent()
35+
.and_then(ast::ExprStmt::cast)
36+
.and_then(|expr| expr.semicolon_token())?
37+
.text_range();
38+
39+
let edit = TextEdit::delete(semicolon);
40+
let source_change =
41+
SourceChange::from_text_edit(d.expr.file_id.original_file(ctx.sema.db), edit);
42+
43+
Some(vec![fix("remove_semicolon", "Remove this semicolon", source_change, semicolon)])
44+
}
45+
46+
#[cfg(test)]
47+
mod tests {
48+
use crate::diagnostics::tests::{check_diagnostics, check_fix};
49+
50+
#[test]
51+
fn missing_semicolon() {
52+
check_diagnostics(
53+
r#"
54+
fn test() -> i32 { 123; }
55+
//^^^ remove this semicolon
56+
"#,
57+
);
58+
}
59+
60+
#[test]
61+
fn remove_semicolon() {
62+
check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
63+
}
64+
}

0 commit comments

Comments
 (0)