diff options
author | Aleksey Kladov <[email protected]> | 2021-04-12 15:58:01 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-04-12 15:58:01 +0100 |
commit | 426d098bd6a032cb03e61d4b3d091caeaecbd4d0 (patch) | |
tree | eb54a5d4e72a875b072af5f266673c6265057f3d /crates/ide/src/diagnostics/fixes.rs | |
parent | cae920a1bb827726aa142e5c81da9e6b0ca38d97 (diff) |
internal: prepare for lazy diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics/fixes.rs')
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index 5fb3e2d91..69cf5288c 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -20,20 +20,21 @@ use syntax::{ | |||
20 | }; | 20 | }; |
21 | use text_edit::TextEdit; | 21 | use text_edit::TextEdit; |
22 | 22 | ||
23 | use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition}; | 23 | use crate::{diagnostics::fix, references::rename::rename_with_semantics, Assist, FilePosition}; |
24 | 24 | ||
25 | /// A [Diagnostic] that potentially has a fix available. | 25 | /// A [Diagnostic] that potentially has a fix available. |
26 | /// | 26 | /// |
27 | /// [Diagnostic]: hir::diagnostics::Diagnostic | 27 | /// [Diagnostic]: hir::diagnostics::Diagnostic |
28 | pub(crate) trait DiagnosticWithFix: Diagnostic { | 28 | pub(crate) trait DiagnosticWithFix: Diagnostic { |
29 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>; | 29 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist>; |
30 | } | 30 | } |
31 | 31 | ||
32 | impl DiagnosticWithFix for UnresolvedModule { | 32 | impl DiagnosticWithFix for UnresolvedModule { |
33 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 33 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
34 | let root = sema.db.parse_or_expand(self.file)?; | 34 | let root = sema.db.parse_or_expand(self.file)?; |
35 | let unresolved_module = self.decl.to_node(&root); | 35 | let unresolved_module = self.decl.to_node(&root); |
36 | Some(Fix::new( | 36 | Some(fix( |
37 | "create_module", | ||
37 | "Create module", | 38 | "Create module", |
38 | FileSystemEdit::CreateFile { | 39 | FileSystemEdit::CreateFile { |
39 | dst: AnchoredPathBuf { | 40 | dst: AnchoredPathBuf { |
@@ -49,7 +50,7 @@ impl DiagnosticWithFix for UnresolvedModule { | |||
49 | } | 50 | } |
50 | 51 | ||
51 | impl DiagnosticWithFix for NoSuchField { | 52 | impl DiagnosticWithFix for NoSuchField { |
52 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 53 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
53 | let root = sema.db.parse_or_expand(self.file)?; | 54 | let root = sema.db.parse_or_expand(self.file)?; |
54 | missing_record_expr_field_fix( | 55 | missing_record_expr_field_fix( |
55 | &sema, | 56 | &sema, |
@@ -60,7 +61,7 @@ impl DiagnosticWithFix for NoSuchField { | |||
60 | } | 61 | } |
61 | 62 | ||
62 | impl DiagnosticWithFix for MissingFields { | 63 | impl DiagnosticWithFix for MissingFields { |
63 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 64 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
64 | // Note that although we could add a diagnostics to | 65 | // Note that although we could add a diagnostics to |
65 | // fill the missing tuple field, e.g : | 66 | // fill the missing tuple field, e.g : |
66 | // `struct A(usize);` | 67 | // `struct A(usize);` |
@@ -86,7 +87,8 @@ impl DiagnosticWithFix for MissingFields { | |||
86 | .into_text_edit(&mut builder); | 87 | .into_text_edit(&mut builder); |
87 | builder.finish() | 88 | builder.finish() |
88 | }; | 89 | }; |
89 | Some(Fix::new( | 90 | Some(fix( |
91 | "fill_missing_fields", | ||
90 | "Fill struct fields", | 92 | "Fill struct fields", |
91 | SourceChange::from_text_edit(self.file.original_file(sema.db), edit), | 93 | SourceChange::from_text_edit(self.file.original_file(sema.db), edit), |
92 | sema.original_range(&field_list_parent.syntax()).range, | 94 | sema.original_range(&field_list_parent.syntax()).range, |
@@ -95,7 +97,7 @@ impl DiagnosticWithFix for MissingFields { | |||
95 | } | 97 | } |
96 | 98 | ||
97 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { | 99 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { |
98 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 100 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
99 | let root = sema.db.parse_or_expand(self.file)?; | 101 | let root = sema.db.parse_or_expand(self.file)?; |
100 | let tail_expr = self.expr.to_node(&root); | 102 | let tail_expr = self.expr.to_node(&root); |
101 | let tail_expr_range = tail_expr.syntax().text_range(); | 103 | let tail_expr_range = tail_expr.syntax().text_range(); |
@@ -103,12 +105,12 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { | |||
103 | let edit = TextEdit::replace(tail_expr_range, replacement); | 105 | let edit = TextEdit::replace(tail_expr_range, replacement); |
104 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); | 106 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); |
105 | let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" }; | 107 | let name = if self.required == "Ok" { "Wrap with Ok" } else { "Wrap with Some" }; |
106 | Some(Fix::new(name, source_change, tail_expr_range)) | 108 | Some(fix("wrap_tail_expr", name, source_change, tail_expr_range)) |
107 | } | 109 | } |
108 | } | 110 | } |
109 | 111 | ||
110 | impl DiagnosticWithFix for RemoveThisSemicolon { | 112 | impl DiagnosticWithFix for RemoveThisSemicolon { |
111 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 113 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
112 | let root = sema.db.parse_or_expand(self.file)?; | 114 | let root = sema.db.parse_or_expand(self.file)?; |
113 | 115 | ||
114 | let semicolon = self | 116 | let semicolon = self |
@@ -123,12 +125,12 @@ impl DiagnosticWithFix for RemoveThisSemicolon { | |||
123 | let edit = TextEdit::delete(semicolon); | 125 | let edit = TextEdit::delete(semicolon); |
124 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); | 126 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); |
125 | 127 | ||
126 | Some(Fix::new("Remove this semicolon", source_change, semicolon)) | 128 | Some(fix("remove_semicolon", "Remove this semicolon", source_change, semicolon)) |
127 | } | 129 | } |
128 | } | 130 | } |
129 | 131 | ||
130 | impl DiagnosticWithFix for IncorrectCase { | 132 | impl DiagnosticWithFix for IncorrectCase { |
131 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 133 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
132 | let root = sema.db.parse_or_expand(self.file)?; | 134 | let root = sema.db.parse_or_expand(self.file)?; |
133 | let name_node = self.ident.to_node(&root); | 135 | let name_node = self.ident.to_node(&root); |
134 | 136 | ||
@@ -140,12 +142,12 @@ impl DiagnosticWithFix for IncorrectCase { | |||
140 | rename_with_semantics(sema, file_position, &self.suggested_text).ok()?; | 142 | rename_with_semantics(sema, file_position, &self.suggested_text).ok()?; |
141 | 143 | ||
142 | let label = format!("Rename to {}", self.suggested_text); | 144 | let label = format!("Rename to {}", self.suggested_text); |
143 | Some(Fix::new(&label, rename_changes, frange.range)) | 145 | Some(fix("change_case", &label, rename_changes, frange.range)) |
144 | } | 146 | } |
145 | } | 147 | } |
146 | 148 | ||
147 | impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { | 149 | impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { |
148 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> { | 150 | fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { |
149 | let root = sema.db.parse_or_expand(self.file)?; | 151 | let root = sema.db.parse_or_expand(self.file)?; |
150 | let next_expr = self.next_expr.to_node(&root); | 152 | let next_expr = self.next_expr.to_node(&root); |
151 | let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?; | 153 | let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?; |
@@ -163,7 +165,8 @@ impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { | |||
163 | 165 | ||
164 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); | 166 | let source_change = SourceChange::from_text_edit(self.file.original_file(sema.db), edit); |
165 | 167 | ||
166 | Some(Fix::new( | 168 | Some(fix( |
169 | "replace_with_find_map", | ||
167 | "Replace filter_map(..).next() with find_map()", | 170 | "Replace filter_map(..).next() with find_map()", |
168 | source_change, | 171 | source_change, |
169 | trigger_range, | 172 | trigger_range, |
@@ -175,7 +178,7 @@ fn missing_record_expr_field_fix( | |||
175 | sema: &Semantics<RootDatabase>, | 178 | sema: &Semantics<RootDatabase>, |
176 | usage_file_id: FileId, | 179 | usage_file_id: FileId, |
177 | record_expr_field: &ast::RecordExprField, | 180 | record_expr_field: &ast::RecordExprField, |
178 | ) -> Option<Fix> { | 181 | ) -> Option<Assist> { |
179 | let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?; | 182 | let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?; |
180 | let def_id = sema.resolve_variant(record_lit)?; | 183 | let def_id = sema.resolve_variant(record_lit)?; |
181 | let module; | 184 | let module; |
@@ -233,7 +236,12 @@ fn missing_record_expr_field_fix( | |||
233 | def_file_id, | 236 | def_file_id, |
234 | TextEdit::insert(last_field_syntax.text_range().end(), new_field), | 237 | TextEdit::insert(last_field_syntax.text_range().end(), new_field), |
235 | ); | 238 | ); |
236 | return Some(Fix::new("Create field", source_change, record_expr_field.syntax().text_range())); | 239 | return Some(fix( |
240 | "create_field", | ||
241 | "Create field", | ||
242 | source_change, | ||
243 | record_expr_field.syntax().text_range(), | ||
244 | )); | ||
237 | 245 | ||
238 | fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { | 246 | fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> { |
239 | match field_def_list { | 247 | match field_def_list { |