aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/diagnostics
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-04-13 09:48:12 +0100
committerAleksey Kladov <[email protected]>2021-04-13 10:09:04 +0100
commit06a633ff421b764428bb946ced914e59532fe13f (patch)
treed608b8a7edd630a8b028c117c615ece9a48c4186 /crates/ide/src/diagnostics
parent04b5fcfdb28f18f4d5279b43c2bb2b3f9c082313 (diff)
feat: improve performance by delaying computation of fixes for diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics')
-rw-r--r--crates/ide/src/diagnostics/fixes.rs38
-rw-r--r--crates/ide/src/diagnostics/unlinked_file.rs2
2 files changed, 26 insertions, 14 deletions
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index 69cf5288c..7be8b3459 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -20,17 +20,26 @@ use syntax::{
20}; 20};
21use text_edit::TextEdit; 21use text_edit::TextEdit;
22 22
23use crate::{diagnostics::fix, references::rename::rename_with_semantics, Assist, FilePosition}; 23use crate::{
24 diagnostics::{fix, unresolved_fix},
25 references::rename::rename_with_semantics,
26 Assist, FilePosition,
27};
24 28
25/// A [Diagnostic] that potentially has a fix available. 29/// A [Diagnostic] that potentially has a fix available.
26/// 30///
27/// [Diagnostic]: hir::diagnostics::Diagnostic 31/// [Diagnostic]: hir::diagnostics::Diagnostic
28pub(crate) trait DiagnosticWithFix: Diagnostic { 32pub(crate) trait DiagnosticWithFix: Diagnostic {
29 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist>; 33 /// `resolve` determines if the diagnostic should fill in the `edit` field
34 /// of the assist.
35 ///
36 /// If `resolve` is false, the edit will be computed later, on demand, and
37 /// can be omitted.
38 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist>;
30} 39}
31 40
32impl DiagnosticWithFix for UnresolvedModule { 41impl DiagnosticWithFix for UnresolvedModule {
33 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 42 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
34 let root = sema.db.parse_or_expand(self.file)?; 43 let root = sema.db.parse_or_expand(self.file)?;
35 let unresolved_module = self.decl.to_node(&root); 44 let unresolved_module = self.decl.to_node(&root);
36 Some(fix( 45 Some(fix(
@@ -50,7 +59,7 @@ impl DiagnosticWithFix for UnresolvedModule {
50} 59}
51 60
52impl DiagnosticWithFix for NoSuchField { 61impl DiagnosticWithFix for NoSuchField {
53 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 62 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
54 let root = sema.db.parse_or_expand(self.file)?; 63 let root = sema.db.parse_or_expand(self.file)?;
55 missing_record_expr_field_fix( 64 missing_record_expr_field_fix(
56 &sema, 65 &sema,
@@ -61,7 +70,7 @@ impl DiagnosticWithFix for NoSuchField {
61} 70}
62 71
63impl DiagnosticWithFix for MissingFields { 72impl DiagnosticWithFix for MissingFields {
64 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 73 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
65 // Note that although we could add a diagnostics to 74 // Note that although we could add a diagnostics to
66 // fill the missing tuple field, e.g : 75 // fill the missing tuple field, e.g :
67 // `struct A(usize);` 76 // `struct A(usize);`
@@ -97,7 +106,7 @@ impl DiagnosticWithFix for MissingFields {
97} 106}
98 107
99impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { 108impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
100 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 109 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
101 let root = sema.db.parse_or_expand(self.file)?; 110 let root = sema.db.parse_or_expand(self.file)?;
102 let tail_expr = self.expr.to_node(&root); 111 let tail_expr = self.expr.to_node(&root);
103 let tail_expr_range = tail_expr.syntax().text_range(); 112 let tail_expr_range = tail_expr.syntax().text_range();
@@ -110,7 +119,7 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
110} 119}
111 120
112impl DiagnosticWithFix for RemoveThisSemicolon { 121impl DiagnosticWithFix for RemoveThisSemicolon {
113 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 122 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
114 let root = sema.db.parse_or_expand(self.file)?; 123 let root = sema.db.parse_or_expand(self.file)?;
115 124
116 let semicolon = self 125 let semicolon = self
@@ -130,7 +139,7 @@ impl DiagnosticWithFix for RemoveThisSemicolon {
130} 139}
131 140
132impl DiagnosticWithFix for IncorrectCase { 141impl DiagnosticWithFix for IncorrectCase {
133 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 142 fn fix(&self, sema: &Semantics<RootDatabase>, resolve: bool) -> Option<Assist> {
134 let root = sema.db.parse_or_expand(self.file)?; 143 let root = sema.db.parse_or_expand(self.file)?;
135 let name_node = self.ident.to_node(&root); 144 let name_node = self.ident.to_node(&root);
136 145
@@ -138,16 +147,19 @@ impl DiagnosticWithFix for IncorrectCase {
138 let frange = name_node.original_file_range(sema.db); 147 let frange = name_node.original_file_range(sema.db);
139 let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() }; 148 let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
140 149
141 let rename_changes =
142 rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;
143
144 let label = format!("Rename to {}", self.suggested_text); 150 let label = format!("Rename to {}", self.suggested_text);
145 Some(fix("change_case", &label, rename_changes, frange.range)) 151 let mut res = unresolved_fix("change_case", &label, frange.range);
152 if resolve {
153 let source_change = rename_with_semantics(sema, file_position, &self.suggested_text);
154 res.source_change = Some(source_change.ok().unwrap_or_default());
155 }
156
157 Some(res)
146 } 158 }
147} 159}
148 160
149impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { 161impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap {
150 fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Assist> { 162 fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
151 let root = sema.db.parse_or_expand(self.file)?; 163 let root = sema.db.parse_or_expand(self.file)?;
152 let next_expr = self.next_expr.to_node(&root); 164 let next_expr = self.next_expr.to_node(&root);
153 let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?; 165 let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?;
diff --git a/crates/ide/src/diagnostics/unlinked_file.rs b/crates/ide/src/diagnostics/unlinked_file.rs
index 5482b7287..7d39f4fbe 100644
--- a/crates/ide/src/diagnostics/unlinked_file.rs
+++ b/crates/ide/src/diagnostics/unlinked_file.rs
@@ -50,7 +50,7 @@ impl Diagnostic for UnlinkedFile {
50} 50}
51 51
52impl DiagnosticWithFix for UnlinkedFile { 52impl DiagnosticWithFix for UnlinkedFile {
53 fn fix(&self, sema: &hir::Semantics<RootDatabase>) -> Option<Assist> { 53 fn fix(&self, sema: &hir::Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> {
54 // If there's an existing module that could add a `mod` item to include the unlinked file, 54 // If there's an existing module that could add a `mod` item to include the unlinked file,
55 // suggest that as a fix. 55 // suggest that as a fix.
56 56