diff options
author | Aleksey Kladov <[email protected]> | 2021-06-13 19:09:03 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-06-13 19:09:03 +0100 |
commit | fc30c5ccbeba2a102922da497809dd3f812544c4 (patch) | |
tree | ed3067580e998f04e94bfb93508fe3f12c851c3b | |
parent | 2ad78924621420cb323efdeb3d875ca3f47d940f (diff) |
internal: refactor incorrect case diagnostics
-rw-r--r-- | crates/hir/src/diagnostics.rs | 29 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 18 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics.rs | 3 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 16 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 1 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/incorrect_case.rs (renamed from crates/ide/src/diagnostics/fixes/change_case.rs) | 61 |
6 files changed, 49 insertions, 79 deletions
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index c294a803b..c2d608eb5 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -34,6 +34,7 @@ macro_rules! diagnostics { | |||
34 | diagnostics![ | 34 | diagnostics![ |
35 | BreakOutsideOfLoop, | 35 | BreakOutsideOfLoop, |
36 | InactiveCode, | 36 | InactiveCode, |
37 | IncorrectCase, | ||
37 | MacroError, | 38 | MacroError, |
38 | MismatchedArgCount, | 39 | MismatchedArgCount, |
39 | MissingFields, | 40 | MissingFields, |
@@ -195,31 +196,3 @@ impl Diagnostic for InternalBailedOut { | |||
195 | } | 196 | } |
196 | 197 | ||
197 | pub use hir_ty::diagnostics::IncorrectCase; | 198 | pub use hir_ty::diagnostics::IncorrectCase; |
198 | |||
199 | impl Diagnostic for IncorrectCase { | ||
200 | fn code(&self) -> DiagnosticCode { | ||
201 | DiagnosticCode("incorrect-ident-case") | ||
202 | } | ||
203 | |||
204 | fn message(&self) -> String { | ||
205 | format!( | ||
206 | "{} `{}` should have {} name, e.g. `{}`", | ||
207 | self.ident_type, | ||
208 | self.ident_text, | ||
209 | self.expected_case.to_string(), | ||
210 | self.suggested_text | ||
211 | ) | ||
212 | } | ||
213 | |||
214 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
215 | InFile::new(self.file, self.ident.clone().into()) | ||
216 | } | ||
217 | |||
218 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
219 | self | ||
220 | } | ||
221 | |||
222 | fn is_experimental(&self) -> bool { | ||
223 | true | ||
224 | } | ||
225 | } | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index b2731b62f..fc147ade3 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -86,8 +86,8 @@ use crate::{ | |||
86 | pub use crate::{ | 86 | pub use crate::{ |
87 | attrs::{HasAttrs, Namespace}, | 87 | attrs::{HasAttrs, Namespace}, |
88 | diagnostics::{ | 88 | diagnostics::{ |
89 | AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, InternalBailedOut, MacroError, | 89 | AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InternalBailedOut, |
90 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, | 90 | MacroError, MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, |
91 | MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, | 91 | MissingUnsafe, NoSuchField, RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, |
92 | UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, | 92 | UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, |
93 | UnresolvedModule, UnresolvedProcMacro, | 93 | UnresolvedModule, UnresolvedProcMacro, |
@@ -340,7 +340,7 @@ impl ModuleDef { | |||
340 | } | 340 | } |
341 | } | 341 | } |
342 | 342 | ||
343 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 343 | pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> { |
344 | let id = match self { | 344 | let id = match self { |
345 | ModuleDef::Adt(it) => match it { | 345 | ModuleDef::Adt(it) => match it { |
346 | Adt::Struct(it) => it.id.into(), | 346 | Adt::Struct(it) => it.id.into(), |
@@ -353,17 +353,19 @@ impl ModuleDef { | |||
353 | ModuleDef::Module(it) => it.id.into(), | 353 | ModuleDef::Module(it) => it.id.into(), |
354 | ModuleDef::Const(it) => it.id.into(), | 354 | ModuleDef::Const(it) => it.id.into(), |
355 | ModuleDef::Static(it) => it.id.into(), | 355 | ModuleDef::Static(it) => it.id.into(), |
356 | _ => return, | 356 | _ => return Vec::new(), |
357 | }; | 357 | }; |
358 | 358 | ||
359 | let module = match self.module(db) { | 359 | let module = match self.module(db) { |
360 | Some(it) => it, | 360 | Some(it) => it, |
361 | None => return, | 361 | None => return Vec::new(), |
362 | }; | 362 | }; |
363 | 363 | ||
364 | let mut acc = Vec::new(); | ||
364 | for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) { | 365 | for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) { |
365 | sink.push(diag) | 366 | acc.push(diag.into()) |
366 | } | 367 | } |
368 | acc | ||
367 | } | 369 | } |
368 | } | 370 | } |
369 | 371 | ||
@@ -624,7 +626,7 @@ impl Module { | |||
624 | acc.extend(m.diagnostics(db, sink, internal_diagnostics)) | 626 | acc.extend(m.diagnostics(db, sink, internal_diagnostics)) |
625 | } | 627 | } |
626 | } | 628 | } |
627 | _ => decl.diagnostics(db, sink), | 629 | _ => acc.extend(decl.diagnostics(db)), |
628 | } | 630 | } |
629 | } | 631 | } |
630 | 632 | ||
@@ -1234,7 +1236,7 @@ impl Function { | |||
1234 | } | 1236 | } |
1235 | 1237 | ||
1236 | for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) { | 1238 | for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) { |
1237 | sink.push(diag) | 1239 | acc.push(diag.into()) |
1238 | } | 1240 | } |
1239 | acc | 1241 | acc |
1240 | } | 1242 | } |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index 407273943..6339c9687 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -84,9 +84,6 @@ impl fmt::Display for IdentType { | |||
84 | } | 84 | } |
85 | } | 85 | } |
86 | 86 | ||
87 | // Diagnostic: incorrect-ident-case | ||
88 | // | ||
89 | // This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention]. | ||
90 | #[derive(Debug)] | 87 | #[derive(Debug)] |
91 | pub struct IncorrectCase { | 88 | pub struct IncorrectCase { |
92 | pub file: HirFileId, | 89 | pub file: HirFileId, |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 814e64ae4..f084f7b06 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | mod break_outside_of_loop; | 7 | mod break_outside_of_loop; |
8 | mod inactive_code; | 8 | mod inactive_code; |
9 | mod incorrect_case; | ||
9 | mod macro_error; | 10 | mod macro_error; |
10 | mod mismatched_arg_count; | 11 | mod mismatched_arg_count; |
11 | mod missing_fields; | 12 | mod missing_fields; |
@@ -135,7 +136,6 @@ pub struct DiagnosticsConfig { | |||
135 | struct DiagnosticsContext<'a> { | 136 | struct DiagnosticsContext<'a> { |
136 | config: &'a DiagnosticsConfig, | 137 | config: &'a DiagnosticsConfig, |
137 | sema: Semantics<'a, RootDatabase>, | 138 | sema: Semantics<'a, RootDatabase>, |
138 | #[allow(unused)] | ||
139 | resolve: &'a AssistResolveStrategy, | 139 | resolve: &'a AssistResolveStrategy, |
140 | } | 140 | } |
141 | 141 | ||
@@ -165,9 +165,6 @@ pub(crate) fn diagnostics( | |||
165 | } | 165 | } |
166 | let res = RefCell::new(res); | 166 | let res = RefCell::new(res); |
167 | let sink_builder = DiagnosticSinkBuilder::new() | 167 | let sink_builder = DiagnosticSinkBuilder::new() |
168 | .on::<hir::diagnostics::IncorrectCase, _>(|d| { | ||
169 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); | ||
170 | }) | ||
171 | .on::<UnlinkedFile, _>(|d| { | 168 | .on::<UnlinkedFile, _>(|d| { |
172 | // Limit diagnostic to the first few characters in the file. This matches how VS Code | 169 | // Limit diagnostic to the first few characters in the file. This matches how VS Code |
173 | // renders it with the full span, but on other editors, and is less invasive. | 170 | // renders it with the full span, but on other editors, and is less invasive. |
@@ -216,6 +213,7 @@ pub(crate) fn diagnostics( | |||
216 | #[rustfmt::skip] | 213 | #[rustfmt::skip] |
217 | let d = match diag { | 214 | let d = match diag { |
218 | AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d), | 215 | AnyDiagnostic::BreakOutsideOfLoop(d) => break_outside_of_loop::break_outside_of_loop(&ctx, &d), |
216 | AnyDiagnostic::IncorrectCase(d) => incorrect_case::incorrect_case(&ctx, &d), | ||
219 | AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), | 217 | AnyDiagnostic::MacroError(d) => macro_error::macro_error(&ctx, &d), |
220 | AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d), | 218 | AnyDiagnostic::MismatchedArgCount(d) => mismatched_arg_count::mismatched_arg_count(&ctx, &d), |
221 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), | 219 | AnyDiagnostic::MissingFields(d) => missing_fields::missing_fields(&ctx, &d), |
@@ -250,16 +248,6 @@ pub(crate) fn diagnostics( | |||
250 | res | 248 | res |
251 | } | 249 | } |
252 | 250 | ||
253 | fn warning_with_fix<D: DiagnosticWithFixes>( | ||
254 | d: &D, | ||
255 | sema: &Semantics<RootDatabase>, | ||
256 | resolve: &AssistResolveStrategy, | ||
257 | ) -> Diagnostic { | ||
258 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) | ||
259 | .with_fixes(d.fixes(sema, resolve)) | ||
260 | .with_code(Some(d.code())) | ||
261 | } | ||
262 | |||
263 | fn check_unnecessary_braces_in_use_statement( | 251 | fn check_unnecessary_braces_in_use_statement( |
264 | acc: &mut Vec<Diagnostic>, | 252 | acc: &mut Vec<Diagnostic>, |
265 | file_id: FileId, | 253 | file_id: FileId, |
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index e4bd90c3f..d763dca93 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -1,6 +1,5 @@ | |||
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; | ||
4 | 3 | ||
5 | use hir::{diagnostics::Diagnostic, Semantics}; | 4 | use hir::{diagnostics::Diagnostic, Semantics}; |
6 | use ide_assists::AssistResolveStrategy; | 5 | use ide_assists::AssistResolveStrategy; |
diff --git a/crates/ide/src/diagnostics/fixes/change_case.rs b/crates/ide/src/diagnostics/incorrect_case.rs index db1a37cd6..56283b58b 100644 --- a/crates/ide/src/diagnostics/fixes/change_case.rs +++ b/crates/ide/src/diagnostics/incorrect_case.rs | |||
@@ -1,35 +1,46 @@ | |||
1 | use hir::{db::AstDatabase, diagnostics::IncorrectCase, InFile, Semantics}; | 1 | use hir::{db::AstDatabase, InFile}; |
2 | use ide_assists::{Assist, AssistResolveStrategy}; | 2 | use ide_assists::Assist; |
3 | use ide_db::{base_db::FilePosition, RootDatabase}; | 3 | use ide_db::base_db::FilePosition; |
4 | use syntax::AstNode; | 4 | use syntax::AstNode; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | diagnostics::{unresolved_fix, DiagnosticWithFixes}, | 7 | diagnostics::{unresolved_fix, Diagnostic, DiagnosticsContext}, |
8 | references::rename::rename_with_semantics, | 8 | references::rename::rename_with_semantics, |
9 | Severity, | ||
9 | }; | 10 | }; |
10 | 11 | ||
11 | impl DiagnosticWithFixes for IncorrectCase { | 12 | // Diagnostic: incorrect-ident-case |
12 | fn fixes( | 13 | // |
13 | &self, | 14 | // This diagnostic is triggered if an item name doesn't follow https://doc.rust-lang.org/1.0.0/style/style/naming/README.html[Rust naming convention]. |
14 | sema: &Semantics<RootDatabase>, | 15 | pub(super) fn incorrect_case(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Diagnostic { |
15 | resolve: &AssistResolveStrategy, | 16 | Diagnostic::new( |
16 | ) -> Option<Vec<Assist>> { | 17 | "incorrect-ident-case", |
17 | let root = sema.db.parse_or_expand(self.file)?; | 18 | format!( |
18 | let name_node = self.ident.to_node(&root); | 19 | "{} `{}` should have {} name, e.g. `{}`", |
19 | 20 | d.ident_type, d.ident_text, d.expected_case, d.suggested_text | |
20 | let name_node = InFile::new(self.file, name_node.syntax()); | 21 | ), |
21 | let frange = name_node.original_file_range(sema.db); | 22 | ctx.sema.diagnostics_display_range(InFile::new(d.file, d.ident.clone().into())).range, |
22 | let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | 23 | ) |
23 | 24 | .severity(Severity::WeakWarning) | |
24 | let label = format!("Rename to {}", self.suggested_text); | 25 | .with_fixes(fixes(ctx, d)) |
25 | let mut res = unresolved_fix("change_case", &label, frange.range); | 26 | } |
26 | if resolve.should_resolve(&res.id) { | 27 | |
27 | let source_change = rename_with_semantics(sema, file_position, &self.suggested_text); | 28 | fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::IncorrectCase) -> Option<Vec<Assist>> { |
28 | res.source_change = Some(source_change.ok().unwrap_or_default()); | 29 | let root = ctx.sema.db.parse_or_expand(d.file)?; |
29 | } | 30 | let name_node = d.ident.to_node(&root); |
30 | 31 | ||
31 | Some(vec![res]) | 32 | let name_node = InFile::new(d.file, name_node.syntax()); |
33 | let frange = name_node.original_file_range(ctx.sema.db); | ||
34 | let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; | ||
35 | |||
36 | let label = format!("Rename to {}", d.suggested_text); | ||
37 | let mut res = unresolved_fix("change_case", &label, frange.range); | ||
38 | if ctx.resolve.should_resolve(&res.id) { | ||
39 | let source_change = rename_with_semantics(&ctx.sema, file_position, &d.suggested_text); | ||
40 | res.source_change = Some(source_change.ok().unwrap_or_default()); | ||
32 | } | 41 | } |
42 | |||
43 | Some(vec![res]) | ||
33 | } | 44 | } |
34 | 45 | ||
35 | #[cfg(test)] | 46 | #[cfg(test)] |