aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics/fixes.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-04-12 15:58:01 +0100
committerAleksey Kladov <[email protected]>2021-04-12 15:58:01 +0100
commit426d098bd6a032cb03e61d4b3d091caeaecbd4d0 (patch)
treeeb54a5d4e72a875b072af5f266673c6265057f3d /crates/ide/src/diagnostics/fixes.rs
parentcae920a1bb827726aa142e5c81da9e6b0ca38d97 (diff)
internal: prepare for lazy diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics/fixes.rs')
-rw-r--r--crates/ide/src/diagnostics/fixes.rs42
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};
21use text_edit::TextEdit; 21use text_edit::TextEdit;
22 22
23use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition}; 23use 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
28pub(crate) trait DiagnosticWithFix: Diagnostic { 28pub(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
32impl DiagnosticWithFix for UnresolvedModule { 32impl 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
51impl DiagnosticWithFix for NoSuchField { 52impl 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
62impl DiagnosticWithFix for MissingFields { 63impl 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
97impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { 99impl 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
110impl DiagnosticWithFix for RemoveThisSemicolon { 112impl 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
130impl DiagnosticWithFix for IncorrectCase { 132impl 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
147impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { 149impl 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 {