aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-06-13 18:13:15 +0100
committerAleksey Kladov <[email protected]>2021-06-13 18:14:12 +0100
commit74f3cca85ab870614f314c6180e2fbb883ad4fe3 (patch)
tree69f0f7aac85ae2fe0a6907a956b94b0bd434ea7e
parent8d391ec981562785ec92ce3afe950972c523f925 (diff)
internal: refactor remove this semicolon diagnostics
-rw-r--r--crates/hir/src/diagnostics.rs22
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/ide/src/diagnostics.rs17
-rw-r--r--crates/ide/src/diagnostics/fixes.rs2
-rw-r--r--crates/ide/src/diagnostics/fixes/create_field.rs1
-rw-r--r--crates/ide/src/diagnostics/fixes/remove_semicolon.rs41
-rw-r--r--crates/ide/src/diagnostics/no_such_field.rs2
-rw-r--r--crates/ide/src/diagnostics/remove_this_semicolon.rs64
8 files changed, 71 insertions, 83 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs
index f839616ce..b144bb335 100644
--- a/crates/hir/src/diagnostics.rs
+++ b/crates/hir/src/diagnostics.rs
@@ -39,6 +39,7 @@ diagnostics![
39 MissingFields, 39 MissingFields,
40 MissingUnsafe, 40 MissingUnsafe,
41 NoSuchField, 41 NoSuchField,
42 RemoveThisSemicolon,
42 UnimplementedBuiltinMacro, 43 UnimplementedBuiltinMacro,
43 UnresolvedExternCrate, 44 UnresolvedExternCrate,
44 UnresolvedImport, 45 UnresolvedImport,
@@ -153,26 +154,7 @@ pub struct MismatchedArgCount {
153 154
154#[derive(Debug)] 155#[derive(Debug)]
155pub struct RemoveThisSemicolon { 156pub struct RemoveThisSemicolon {
156 pub file: HirFileId, 157 pub expr: InFile<AstPtr<ast::Expr>>,
157 pub expr: AstPtr<ast::Expr>,
158}
159
160impl 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 }
176} 158}
177 159
178// Diagnostic: missing-ok-or-some-in-tail-expr 160// Diagnostic: missing-ok-or-some-in-tail-expr
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index c1af5f097..cb9bf60b8 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1184,10 +1184,7 @@ impl Function {
1184 } 1184 }
1185 BodyValidationDiagnostic::RemoveThisSemicolon { expr } => { 1185 BodyValidationDiagnostic::RemoveThisSemicolon { expr } => {
1186 match source_map.expr_syntax(expr) { 1186 match source_map.expr_syntax(expr) {
1187 Ok(source_ptr) => sink.push(RemoveThisSemicolon { 1187 Ok(expr) => acc.push(RemoveThisSemicolon { expr }.into()),
1188 file: source_ptr.file_id,
1189 expr: source_ptr.value,
1190 }),
1191 Err(SyntheticSyntax) => (), 1188 Err(SyntheticSyntax) => (),
1192 } 1189 }
1193 } 1190 }
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 4c92d0cf4..3ced08f30 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -11,6 +11,7 @@ mod mismatched_arg_count;
11mod missing_fields; 11mod missing_fields;
12mod missing_unsafe; 12mod missing_unsafe;
13mod no_such_field; 13mod no_such_field;
14mod remove_this_semicolon;
14mod unimplemented_builtin_macro; 15mod unimplemented_builtin_macro;
15mod unresolved_extern_crate; 16mod unresolved_extern_crate;
16mod unresolved_import; 17mod unresolved_import;
@@ -165,9 +166,6 @@ pub(crate) fn diagnostics(
165 .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| { 166 .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| {
166 res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); 167 res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
167 }) 168 })
168 .on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| {
169 res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve));
170 })
171 .on::<hir::diagnostics::IncorrectCase, _>(|d| { 169 .on::<hir::diagnostics::IncorrectCase, _>(|d| {
172 res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); 170 res.borrow_mut().push(warning_with_fix(d, &sema, resolve));
173 }) 171 })
@@ -223,10 +221,11 @@ pub(crate) fn diagnostics(
223 let d = match diag { 221 let d = match diag {
224 AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d), 222 AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d),
225 AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), 223 AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d),
224 AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
226 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), 225 AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d),
227 AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d), 226 AnyDiagnostic::MissingUnsafe(d) => missing_unsafe::missing_unsafe(&ctx, &d),
228 AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d),
229 AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d), 227 AnyDiagnostic::NoSuchField(d) => no_such_field::no_such_field(&ctx, &d),
228 AnyDiagnostic::RemoveThisSemicolon(d) => remove_this_semicolon::remove_this_semicolon(&ctx, &d),
230 AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d), 229 AnyDiagnostic::UnimplementedBuiltinMacro(d) => unimplemented_builtin_macro::unimplemented_builtin_macro(&ctx, &d),
231 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d), 230 AnyDiagnostic::UnresolvedExternCrate(d) => unresolved_extern_crate::unresolved_extern_crate(&ctx, &d),
232 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d), 231 AnyDiagnostic::UnresolvedImport(d) => unresolved_import::unresolved_import(&ctx, &d),
@@ -839,16 +838,6 @@ fn x(a: S) {
839 } 838 }
840 839
841 #[test] 840 #[test]
842 fn missing_semicolon() {
843 check_diagnostics(
844 r#"
845 fn test() -> i32 { 123; }
846 //^^^ Remove this semicolon
847 "#,
848 );
849 }
850
851 #[test]
852 fn import_extern_crate_clash_with_inner_item() { 841 fn import_extern_crate_clash_with_inner_item() {
853 // This is more of a resolver test, but doesn't really work with the hir_def testsuite. 842 // This is more of a resolver test, but doesn't really work with the hir_def testsuite.
854 843
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index a2e792b3b..70f17881e 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -1,8 +1,6 @@
1//! Provides a way to attach fixes to the diagnostics. 1//! Provides a way to attach fixes to the diagnostics.
2//! The same module also has all curret custom fixes for the diagnostics implemented. 2//! The same module also has all curret custom fixes for the diagnostics implemented.
3mod change_case; 3mod change_case;
4mod create_field;
5mod remove_semicolon;
6mod replace_with_find_map; 4mod replace_with_find_map;
7mod wrap_tail_expr; 5mod wrap_tail_expr;
8 6
diff --git a/crates/ide/src/diagnostics/fixes/create_field.rs b/crates/ide/src/diagnostics/fixes/create_field.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/crates/ide/src/diagnostics/fixes/create_field.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/crates/ide/src/diagnostics/fixes/remove_semicolon.rs b/crates/ide/src/diagnostics/fixes/remove_semicolon.rs
deleted file mode 100644
index f1724d479..000000000
--- a/crates/ide/src/diagnostics/fixes/remove_semicolon.rs
+++ /dev/null
@@ -1,41 +0,0 @@
1use hir::{db::AstDatabase, diagnostics::RemoveThisSemicolon, Semantics};
2use ide_assists::{Assist, AssistResolveStrategy};
3use ide_db::{source_change::SourceChange, RootDatabase};
4use syntax::{ast, AstNode};
5use text_edit::TextEdit;
6
7use crate::diagnostics::{fix, DiagnosticWithFixes};
8
9impl DiagnosticWithFixes for RemoveThisSemicolon {
10 fn fixes(
11 &self,
12 sema: &Semantics<RootDatabase>,
13 _resolve: &AssistResolveStrategy,
14 ) -> Option<Vec<Assist>> {
15 let root = sema.db.parse_or_expand(self.file)?;
16
17 let semicolon = self
18 .expr
19 .to_node(&root)
20 .syntax()
21 .parent()
22 .and_then(ast::ExprStmt::cast)
23 .and_then(|expr| expr.semicolon_token())?
24 .text_range();
25
26 let edit = TextEdit::delete(semicolon);
27 let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit);
28
29 Some(vec![fix("remove_semicolon", "Remove this semicolon", source_change, semicolon)])
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::diagnostics::tests::check_fix;
36
37 #[test]
38 fn remove_semicolon() {
39 check_fix(r#"fn f() -> i32 { 92$0; }"#, r#"fn f() -> i32 { 92 }"#);
40 }
41}
diff --git a/crates/ide/src/diagnostics/no_such_field.rs b/crates/ide/src/diagnostics/no_such_field.rs
index 61962de28..edc63c246 100644
--- a/crates/ide/src/diagnostics/no_such_field.rs
+++ b/crates/ide/src/diagnostics/no_such_field.rs
@@ -17,7 +17,7 @@ use crate::{
17pub(super) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic { 17pub(super) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic {
18 Diagnostic::new( 18 Diagnostic::new(
19 "no-such-field", 19 "no-such-field",
20 "no such field".to_string(), 20 "no such field",
21 ctx.sema.diagnostics_display_range(d.field.clone().map(|it| it.into())).range, 21 ctx.sema.diagnostics_display_range(d.field.clone().map(|it| it.into())).range,
22 ) 22 )
23 .with_fixes(fixes(ctx, d)) 23 .with_fixes(fixes(ctx, d))
diff --git a/crates/ide/src/diagnostics/remove_this_semicolon.rs b/crates/ide/src/diagnostics/remove_this_semicolon.rs
new file mode 100644
index 000000000..814cb0f8c
--- /dev/null
+++ b/crates/ide/src/diagnostics/remove_this_semicolon.rs
@@ -0,0 +1,64 @@
1use hir::db::AstDatabase;
2use ide_db::source_change::SourceChange;
3use syntax::{ast, AstNode};
4use text_edit::TextEdit;
5
6use 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.
14pub(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
26fn 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)]
47mod tests {
48 use crate::diagnostics::tests::{check_diagnostics, check_fix};
49
50 #[test]
51 fn missing_semicolon() {
52 check_diagnostics(
53 r#"
54fn 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}