diff options
author | Aleksey Kladov <[email protected]> | 2021-04-13 09:48:12 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2021-04-13 10:09:04 +0100 |
commit | 06a633ff421b764428bb946ced914e59532fe13f (patch) | |
tree | d608b8a7edd630a8b028c117c615ece9a48c4186 /crates/ide/src/diagnostics | |
parent | 04b5fcfdb28f18f4d5279b43c2bb2b3f9c082313 (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.rs | 38 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/unlinked_file.rs | 2 |
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 | }; |
21 | use text_edit::TextEdit; | 21 | use text_edit::TextEdit; |
22 | 22 | ||
23 | use crate::{diagnostics::fix, references::rename::rename_with_semantics, Assist, FilePosition}; | 23 | use 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 |
28 | pub(crate) trait DiagnosticWithFix: Diagnostic { | 32 | pub(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 | ||
32 | impl DiagnosticWithFix for UnresolvedModule { | 41 | impl 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 | ||
52 | impl DiagnosticWithFix for NoSuchField { | 61 | impl 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 | ||
63 | impl DiagnosticWithFix for MissingFields { | 72 | impl 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 | ||
99 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { | 108 | impl 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 | ||
112 | impl DiagnosticWithFix for RemoveThisSemicolon { | 121 | impl 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 | ||
132 | impl DiagnosticWithFix for IncorrectCase { | 141 | impl 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 | ||
149 | impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { | 161 | impl 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 | ||
52 | impl DiagnosticWithFix for UnlinkedFile { | 52 | impl 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 | ||