diff options
author | Aleksey Kladov <[email protected]> | 2021-06-13 18:13:15 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-06-13 18:14:12 +0100 |
commit | 74f3cca85ab870614f314c6180e2fbb883ad4fe3 (patch) | |
tree | 69f0f7aac85ae2fe0a6907a956b94b0bd434ea7e | |
parent | 8d391ec981562785ec92ce3afe950972c523f925 (diff) |
internal: refactor remove this semicolon diagnostics
-rw-r--r-- | crates/hir/src/diagnostics.rs | 22 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 17 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes/create_field.rs | 1 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes/remove_semicolon.rs | 41 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/no_such_field.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/remove_this_semicolon.rs | 64 |
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)] |
155 | pub struct RemoveThisSemicolon { | 156 | pub struct RemoveThisSemicolon { |
156 | pub file: HirFileId, | 157 | pub expr: InFile<AstPtr<ast::Expr>>, |
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 | } | ||
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; | |||
11 | mod missing_fields; | 11 | mod missing_fields; |
12 | mod missing_unsafe; | 12 | mod missing_unsafe; |
13 | mod no_such_field; | 13 | mod no_such_field; |
14 | mod remove_this_semicolon; | ||
14 | mod unimplemented_builtin_macro; | 15 | mod unimplemented_builtin_macro; |
15 | mod unresolved_extern_crate; | 16 | mod unresolved_extern_crate; |
16 | mod unresolved_import; | 17 | mod 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. |
3 | mod change_case; | 3 | mod change_case; |
4 | mod create_field; | ||
5 | mod remove_semicolon; | ||
6 | mod replace_with_find_map; | 4 | mod replace_with_find_map; |
7 | mod wrap_tail_expr; | 5 | mod 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 @@ | |||
1 | use hir::{db::AstDatabase, diagnostics::RemoveThisSemicolon, Semantics}; | ||
2 | use ide_assists::{Assist, AssistResolveStrategy}; | ||
3 | use ide_db::{source_change::SourceChange, RootDatabase}; | ||
4 | use syntax::{ast, AstNode}; | ||
5 | use text_edit::TextEdit; | ||
6 | |||
7 | use crate::diagnostics::{fix, DiagnosticWithFixes}; | ||
8 | |||
9 | impl 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)] | ||
34 | mod 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::{ | |||
17 | pub(super) fn no_such_field(ctx: &DiagnosticsContext<'_>, d: &hir::NoSuchField) -> Diagnostic { | 17 | pub(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 @@ | |||
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 | } | ||