diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 43 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/fixes.rs | 51 | ||||
-rw-r--r-- | crates/ide/src/diagnostics/unlinked_file.rs | 7 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 35 | ||||
-rw-r--r-- | crates/ide/src/ssr.rs | 55 |
5 files changed, 123 insertions, 68 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 1c911a8b2..455f20c93 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -15,6 +15,7 @@ use hir::{ | |||
15 | diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, | 15 | diagnostics::{Diagnostic as _, DiagnosticCode, DiagnosticSinkBuilder}, |
16 | InFile, Semantics, | 16 | InFile, Semantics, |
17 | }; | 17 | }; |
18 | use ide_assists::AssistResolveStrategy; | ||
18 | use ide_db::{base_db::SourceDatabase, RootDatabase}; | 19 | use ide_db::{base_db::SourceDatabase, RootDatabase}; |
19 | use itertools::Itertools; | 20 | use itertools::Itertools; |
20 | use rustc_hash::FxHashSet; | 21 | use rustc_hash::FxHashSet; |
@@ -84,7 +85,7 @@ pub struct DiagnosticsConfig { | |||
84 | pub(crate) fn diagnostics( | 85 | pub(crate) fn diagnostics( |
85 | db: &RootDatabase, | 86 | db: &RootDatabase, |
86 | config: &DiagnosticsConfig, | 87 | config: &DiagnosticsConfig, |
87 | resolve: bool, | 88 | resolve: AssistResolveStrategy, |
88 | file_id: FileId, | 89 | file_id: FileId, |
89 | ) -> Vec<Diagnostic> { | 90 | ) -> Vec<Diagnostic> { |
90 | let _p = profile::span("diagnostics"); | 91 | let _p = profile::span("diagnostics"); |
@@ -212,7 +213,7 @@ pub(crate) fn diagnostics( | |||
212 | fn diagnostic_with_fix<D: DiagnosticWithFix>( | 213 | fn diagnostic_with_fix<D: DiagnosticWithFix>( |
213 | d: &D, | 214 | d: &D, |
214 | sema: &Semantics<RootDatabase>, | 215 | sema: &Semantics<RootDatabase>, |
215 | resolve: bool, | 216 | resolve: AssistResolveStrategy, |
216 | ) -> Diagnostic { | 217 | ) -> Diagnostic { |
217 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) | 218 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
218 | .with_fix(d.fix(&sema, resolve)) | 219 | .with_fix(d.fix(&sema, resolve)) |
@@ -222,7 +223,7 @@ fn diagnostic_with_fix<D: DiagnosticWithFix>( | |||
222 | fn warning_with_fix<D: DiagnosticWithFix>( | 223 | fn warning_with_fix<D: DiagnosticWithFix>( |
223 | d: &D, | 224 | d: &D, |
224 | sema: &Semantics<RootDatabase>, | 225 | sema: &Semantics<RootDatabase>, |
225 | resolve: bool, | 226 | resolve: AssistResolveStrategy, |
226 | ) -> Diagnostic { | 227 | ) -> Diagnostic { |
227 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) | 228 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
228 | .with_fix(d.fix(&sema, resolve)) | 229 | .with_fix(d.fix(&sema, resolve)) |
@@ -299,6 +300,7 @@ fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { | |||
299 | #[cfg(test)] | 300 | #[cfg(test)] |
300 | mod tests { | 301 | mod tests { |
301 | use expect_test::{expect, Expect}; | 302 | use expect_test::{expect, Expect}; |
303 | use ide_assists::AssistResolveStrategy; | ||
302 | use stdx::trim_indent; | 304 | use stdx::trim_indent; |
303 | use test_utils::assert_eq_text; | 305 | use test_utils::assert_eq_text; |
304 | 306 | ||
@@ -314,7 +316,11 @@ mod tests { | |||
314 | 316 | ||
315 | let (analysis, file_position) = fixture::position(ra_fixture_before); | 317 | let (analysis, file_position) = fixture::position(ra_fixture_before); |
316 | let diagnostic = analysis | 318 | let diagnostic = analysis |
317 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) | 319 | .diagnostics( |
320 | &DiagnosticsConfig::default(), | ||
321 | AssistResolveStrategy::All, | ||
322 | file_position.file_id, | ||
323 | ) | ||
318 | .unwrap() | 324 | .unwrap() |
319 | .pop() | 325 | .pop() |
320 | .unwrap(); | 326 | .unwrap(); |
@@ -343,7 +349,11 @@ mod tests { | |||
343 | fn check_no_fix(ra_fixture: &str) { | 349 | fn check_no_fix(ra_fixture: &str) { |
344 | let (analysis, file_position) = fixture::position(ra_fixture); | 350 | let (analysis, file_position) = fixture::position(ra_fixture); |
345 | let diagnostic = analysis | 351 | let diagnostic = analysis |
346 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) | 352 | .diagnostics( |
353 | &DiagnosticsConfig::default(), | ||
354 | AssistResolveStrategy::All, | ||
355 | file_position.file_id, | ||
356 | ) | ||
347 | .unwrap() | 357 | .unwrap() |
348 | .pop() | 358 | .pop() |
349 | .unwrap(); | 359 | .unwrap(); |
@@ -357,7 +367,9 @@ mod tests { | |||
357 | let diagnostics = files | 367 | let diagnostics = files |
358 | .into_iter() | 368 | .into_iter() |
359 | .flat_map(|file_id| { | 369 | .flat_map(|file_id| { |
360 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap() | 370 | analysis |
371 | .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id) | ||
372 | .unwrap() | ||
361 | }) | 373 | }) |
362 | .collect::<Vec<_>>(); | 374 | .collect::<Vec<_>>(); |
363 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | 375 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); |
@@ -365,8 +377,9 @@ mod tests { | |||
365 | 377 | ||
366 | fn check_expect(ra_fixture: &str, expect: Expect) { | 378 | fn check_expect(ra_fixture: &str, expect: Expect) { |
367 | let (analysis, file_id) = fixture::file(ra_fixture); | 379 | let (analysis, file_id) = fixture::file(ra_fixture); |
368 | let diagnostics = | 380 | let diagnostics = analysis |
369 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap(); | 381 | .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id) |
382 | .unwrap(); | ||
370 | expect.assert_debug_eq(&diagnostics) | 383 | expect.assert_debug_eq(&diagnostics) |
371 | } | 384 | } |
372 | 385 | ||
@@ -911,11 +924,13 @@ struct Foo { | |||
911 | 924 | ||
912 | let (analysis, file_id) = fixture::file(r#"mod foo;"#); | 925 | let (analysis, file_id) = fixture::file(r#"mod foo;"#); |
913 | 926 | ||
914 | let diagnostics = analysis.diagnostics(&config, true, file_id).unwrap(); | 927 | let diagnostics = |
928 | analysis.diagnostics(&config, AssistResolveStrategy::All, file_id).unwrap(); | ||
915 | assert!(diagnostics.is_empty()); | 929 | assert!(diagnostics.is_empty()); |
916 | 930 | ||
917 | let diagnostics = | 931 | let diagnostics = analysis |
918 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap(); | 932 | .diagnostics(&DiagnosticsConfig::default(), AssistResolveStrategy::All, file_id) |
933 | .unwrap(); | ||
919 | assert!(!diagnostics.is_empty()); | 934 | assert!(!diagnostics.is_empty()); |
920 | } | 935 | } |
921 | 936 | ||
@@ -1022,7 +1037,11 @@ impl TestStruct { | |||
1022 | 1037 | ||
1023 | let (analysis, file_position) = fixture::position(input); | 1038 | let (analysis, file_position) = fixture::position(input); |
1024 | let diagnostics = analysis | 1039 | let diagnostics = analysis |
1025 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) | 1040 | .diagnostics( |
1041 | &DiagnosticsConfig::default(), | ||
1042 | AssistResolveStrategy::All, | ||
1043 | file_position.file_id, | ||
1044 | ) | ||
1026 | .unwrap(); | 1045 | .unwrap(); |
1027 | assert_eq!(diagnostics.len(), 1); | 1046 | assert_eq!(diagnostics.len(), 1); |
1028 | 1047 | ||
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index 7be8b3459..f23064eac 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -8,6 +8,7 @@ use hir::{ | |||
8 | }, | 8 | }, |
9 | HasSource, HirDisplay, InFile, Semantics, VariantDef, | 9 | HasSource, HirDisplay, InFile, Semantics, VariantDef, |
10 | }; | 10 | }; |
11 | use ide_assists::AssistResolveStrategy; | ||
11 | use ide_db::{ | 12 | use ide_db::{ |
12 | base_db::{AnchoredPathBuf, FileId}, | 13 | base_db::{AnchoredPathBuf, FileId}, |
13 | source_change::{FileSystemEdit, SourceChange}, | 14 | source_change::{FileSystemEdit, SourceChange}, |
@@ -35,11 +36,19 @@ pub(crate) trait DiagnosticWithFix: Diagnostic { | |||
35 | /// | 36 | /// |
36 | /// If `resolve` is false, the edit will be computed later, on demand, and | 37 | /// If `resolve` is false, the edit will be computed later, on demand, and |
37 | /// can be omitted. | 38 | /// can be omitted. |
38 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist>; | 39 | fn fix( |
40 | &self, | ||
41 | sema: &Semantics<RootDatabase>, | ||
42 | _resolve: AssistResolveStrategy, | ||
43 | ) -> Option<Assist>; | ||
39 | } | 44 | } |
40 | 45 | ||
41 | impl DiagnosticWithFix for UnresolvedModule { | 46 | impl DiagnosticWithFix for UnresolvedModule { |
42 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 47 | fn fix( |
48 | &self, | ||
49 | sema: &Semantics<RootDatabase>, | ||
50 | _resolve: AssistResolveStrategy, | ||
51 | ) -> Option<Assist> { | ||
43 | let root = sema.db.parse_or_expand(self.file)?; | 52 | let root = sema.db.parse_or_expand(self.file)?; |
44 | let unresolved_module = self.decl.to_node(&root); | 53 | let unresolved_module = self.decl.to_node(&root); |
45 | Some(fix( | 54 | Some(fix( |
@@ -59,7 +68,11 @@ impl DiagnosticWithFix for UnresolvedModule { | |||
59 | } | 68 | } |
60 | 69 | ||
61 | impl DiagnosticWithFix for NoSuchField { | 70 | impl DiagnosticWithFix for NoSuchField { |
62 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 71 | fn fix( |
72 | &self, | ||
73 | sema: &Semantics<RootDatabase>, | ||
74 | _resolve: AssistResolveStrategy, | ||
75 | ) -> Option<Assist> { | ||
63 | let root = sema.db.parse_or_expand(self.file)?; | 76 | let root = sema.db.parse_or_expand(self.file)?; |
64 | missing_record_expr_field_fix( | 77 | missing_record_expr_field_fix( |
65 | &sema, | 78 | &sema, |
@@ -70,7 +83,11 @@ impl DiagnosticWithFix for NoSuchField { | |||
70 | } | 83 | } |
71 | 84 | ||
72 | impl DiagnosticWithFix for MissingFields { | 85 | impl DiagnosticWithFix for MissingFields { |
73 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 86 | fn fix( |
87 | &self, | ||
88 | sema: &Semantics<RootDatabase>, | ||
89 | _resolve: AssistResolveStrategy, | ||
90 | ) -> Option<Assist> { | ||
74 | // Note that although we could add a diagnostics to | 91 | // Note that although we could add a diagnostics to |
75 | // fill the missing tuple field, e.g : | 92 | // fill the missing tuple field, e.g : |
76 | // `struct A(usize);` | 93 | // `struct A(usize);` |
@@ -106,7 +123,11 @@ impl DiagnosticWithFix for MissingFields { | |||
106 | } | 123 | } |
107 | 124 | ||
108 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { | 125 | impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { |
109 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 126 | fn fix( |
127 | &self, | ||
128 | sema: &Semantics<RootDatabase>, | ||
129 | _resolve: AssistResolveStrategy, | ||
130 | ) -> Option<Assist> { | ||
110 | let root = sema.db.parse_or_expand(self.file)?; | 131 | let root = sema.db.parse_or_expand(self.file)?; |
111 | let tail_expr = self.expr.to_node(&root); | 132 | let tail_expr = self.expr.to_node(&root); |
112 | let tail_expr_range = tail_expr.syntax().text_range(); | 133 | let tail_expr_range = tail_expr.syntax().text_range(); |
@@ -119,7 +140,11 @@ impl DiagnosticWithFix for MissingOkOrSomeInTailExpr { | |||
119 | } | 140 | } |
120 | 141 | ||
121 | impl DiagnosticWithFix for RemoveThisSemicolon { | 142 | impl DiagnosticWithFix for RemoveThisSemicolon { |
122 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 143 | fn fix( |
144 | &self, | ||
145 | sema: &Semantics<RootDatabase>, | ||
146 | _resolve: AssistResolveStrategy, | ||
147 | ) -> Option<Assist> { | ||
123 | let root = sema.db.parse_or_expand(self.file)?; | 148 | let root = sema.db.parse_or_expand(self.file)?; |
124 | 149 | ||
125 | let semicolon = self | 150 | let semicolon = self |
@@ -139,7 +164,11 @@ impl DiagnosticWithFix for RemoveThisSemicolon { | |||
139 | } | 164 | } |
140 | 165 | ||
141 | impl DiagnosticWithFix for IncorrectCase { | 166 | impl DiagnosticWithFix for IncorrectCase { |
142 | fn fix(&self, sema: &Semantics<RootDatabase>, resolve: bool) -> Option<Assist> { | 167 | fn fix( |
168 | &self, | ||
169 | sema: &Semantics<RootDatabase>, | ||
170 | resolve: AssistResolveStrategy, | ||
171 | ) -> Option<Assist> { | ||
143 | let root = sema.db.parse_or_expand(self.file)?; | 172 | let root = sema.db.parse_or_expand(self.file)?; |
144 | let name_node = self.ident.to_node(&root); | 173 | let name_node = self.ident.to_node(&root); |
145 | 174 | ||
@@ -149,7 +178,7 @@ impl DiagnosticWithFix for IncorrectCase { | |||
149 | 178 | ||
150 | let label = format!("Rename to {}", self.suggested_text); | 179 | let label = format!("Rename to {}", self.suggested_text); |
151 | let mut res = unresolved_fix("change_case", &label, frange.range); | 180 | let mut res = unresolved_fix("change_case", &label, frange.range); |
152 | if resolve { | 181 | if resolve.should_resolve(&res.id) { |
153 | let source_change = rename_with_semantics(sema, file_position, &self.suggested_text); | 182 | let source_change = rename_with_semantics(sema, file_position, &self.suggested_text); |
154 | res.source_change = Some(source_change.ok().unwrap_or_default()); | 183 | res.source_change = Some(source_change.ok().unwrap_or_default()); |
155 | } | 184 | } |
@@ -159,7 +188,11 @@ impl DiagnosticWithFix for IncorrectCase { | |||
159 | } | 188 | } |
160 | 189 | ||
161 | impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { | 190 | impl DiagnosticWithFix for ReplaceFilterMapNextWithFindMap { |
162 | fn fix(&self, sema: &Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 191 | fn fix( |
192 | &self, | ||
193 | sema: &Semantics<RootDatabase>, | ||
194 | _resolve: AssistResolveStrategy, | ||
195 | ) -> Option<Assist> { | ||
163 | let root = sema.db.parse_or_expand(self.file)?; | 196 | let root = sema.db.parse_or_expand(self.file)?; |
164 | let next_expr = self.next_expr.to_node(&root); | 197 | let next_expr = self.next_expr.to_node(&root); |
165 | let next_call = ast::MethodCallExpr::cast(next_expr.syntax().clone())?; | 198 | 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 7d39f4fbe..e48528bed 100644 --- a/crates/ide/src/diagnostics/unlinked_file.rs +++ b/crates/ide/src/diagnostics/unlinked_file.rs | |||
@@ -5,6 +5,7 @@ use hir::{ | |||
5 | diagnostics::{Diagnostic, DiagnosticCode}, | 5 | diagnostics::{Diagnostic, DiagnosticCode}, |
6 | InFile, | 6 | InFile, |
7 | }; | 7 | }; |
8 | use ide_assists::AssistResolveStrategy; | ||
8 | use ide_db::{ | 9 | use ide_db::{ |
9 | base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt}, | 10 | base_db::{FileId, FileLoader, SourceDatabase, SourceDatabaseExt}, |
10 | source_change::SourceChange, | 11 | source_change::SourceChange, |
@@ -50,7 +51,11 @@ impl Diagnostic for UnlinkedFile { | |||
50 | } | 51 | } |
51 | 52 | ||
52 | impl DiagnosticWithFix for UnlinkedFile { | 53 | impl DiagnosticWithFix for UnlinkedFile { |
53 | fn fix(&self, sema: &hir::Semantics<RootDatabase>, _resolve: bool) -> Option<Assist> { | 54 | fn fix( |
55 | &self, | ||
56 | sema: &hir::Semantics<RootDatabase>, | ||
57 | _resolve: AssistResolveStrategy, | ||
58 | ) -> Option<Assist> { | ||
54 | // If there's an existing module that could add a `mod` item to include the unlinked file, | 59 | // If there's an existing module that could add a `mod` item to include the unlinked file, |
55 | // suggest that as a fix. | 60 | // suggest that as a fix. |
56 | 61 | ||
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 99e45633e..6847b7e83 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -87,7 +87,7 @@ pub use crate::{ | |||
87 | }, | 87 | }, |
88 | }; | 88 | }; |
89 | pub use hir::{Documentation, Semantics}; | 89 | pub use hir::{Documentation, Semantics}; |
90 | pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind}; | 90 | pub use ide_assists::{Assist, AssistConfig, AssistId, AssistKind, AssistResolveStrategy}; |
91 | pub use ide_completion::{ | 91 | pub use ide_completion::{ |
92 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit, | 92 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit, |
93 | InsertTextFormat, | 93 | InsertTextFormat, |
@@ -518,12 +518,13 @@ impl Analysis { | |||
518 | pub fn assists( | 518 | pub fn assists( |
519 | &self, | 519 | &self, |
520 | config: &AssistConfig, | 520 | config: &AssistConfig, |
521 | resolve: bool, | 521 | resolve: AssistResolveStrategy, |
522 | frange: FileRange, | 522 | frange: FileRange, |
523 | ) -> Cancelable<Vec<Assist>> { | 523 | ) -> Cancelable<Vec<Assist>> { |
524 | self.with_db(|db| { | 524 | self.with_db(|db| { |
525 | let ssr_assists = ssr::ssr_assists(db, resolve, frange); | ||
525 | let mut acc = Assist::get(db, config, resolve, frange); | 526 | let mut acc = Assist::get(db, config, resolve, frange); |
526 | ssr::add_ssr_assist(db, &mut acc, resolve, frange); | 527 | acc.extend(ssr_assists.into_iter()); |
527 | acc | 528 | acc |
528 | }) | 529 | }) |
529 | } | 530 | } |
@@ -532,7 +533,7 @@ impl Analysis { | |||
532 | pub fn diagnostics( | 533 | pub fn diagnostics( |
533 | &self, | 534 | &self, |
534 | config: &DiagnosticsConfig, | 535 | config: &DiagnosticsConfig, |
535 | resolve: bool, | 536 | resolve: AssistResolveStrategy, |
536 | file_id: FileId, | 537 | file_id: FileId, |
537 | ) -> Cancelable<Vec<Diagnostic>> { | 538 | ) -> Cancelable<Vec<Diagnostic>> { |
538 | self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id)) | 539 | self.with_db(|db| diagnostics::diagnostics(db, config, resolve, file_id)) |
@@ -543,7 +544,7 @@ impl Analysis { | |||
543 | &self, | 544 | &self, |
544 | assist_config: &AssistConfig, | 545 | assist_config: &AssistConfig, |
545 | diagnostics_config: &DiagnosticsConfig, | 546 | diagnostics_config: &DiagnosticsConfig, |
546 | resolve: bool, | 547 | resolve: AssistResolveStrategy, |
547 | frange: FileRange, | 548 | frange: FileRange, |
548 | ) -> Cancelable<Vec<Assist>> { | 549 | ) -> Cancelable<Vec<Assist>> { |
549 | let include_fixes = match &assist_config.allowed { | 550 | let include_fixes = match &assist_config.allowed { |
@@ -552,17 +553,21 @@ impl Analysis { | |||
552 | }; | 553 | }; |
553 | 554 | ||
554 | self.with_db(|db| { | 555 | self.with_db(|db| { |
556 | let ssr_assists = ssr::ssr_assists(db, resolve, frange); | ||
557 | let diagnostic_assists = if include_fixes { | ||
558 | diagnostics::diagnostics(db, diagnostics_config, resolve, frange.file_id) | ||
559 | .into_iter() | ||
560 | .filter_map(|it| it.fix) | ||
561 | .filter(|it| it.target.intersect(frange.range).is_some()) | ||
562 | .collect() | ||
563 | } else { | ||
564 | Vec::new() | ||
565 | }; | ||
566 | |||
555 | let mut res = Assist::get(db, assist_config, resolve, frange); | 567 | let mut res = Assist::get(db, assist_config, resolve, frange); |
556 | ssr::add_ssr_assist(db, &mut res, resolve, frange); | 568 | res.extend(ssr_assists.into_iter()); |
557 | 569 | res.extend(diagnostic_assists.into_iter()); | |
558 | if include_fixes { | 570 | |
559 | res.extend( | ||
560 | diagnostics::diagnostics(db, diagnostics_config, resolve, frange.file_id) | ||
561 | .into_iter() | ||
562 | .filter_map(|it| it.fix) | ||
563 | .filter(|it| it.target.intersect(frange.range).is_some()), | ||
564 | ); | ||
565 | } | ||
566 | res | 571 | res |
567 | }) | 572 | }) |
568 | } | 573 | } |
diff --git a/crates/ide/src/ssr.rs b/crates/ide/src/ssr.rs index f3638d928..785ce3010 100644 --- a/crates/ide/src/ssr.rs +++ b/crates/ide/src/ssr.rs | |||
@@ -2,18 +2,23 @@ | |||
2 | //! assist in ide_assists because that would require the ide_assists crate | 2 | //! assist in ide_assists because that would require the ide_assists crate |
3 | //! depend on the ide_ssr crate. | 3 | //! depend on the ide_ssr crate. |
4 | 4 | ||
5 | use ide_assists::{Assist, AssistId, AssistKind, GroupLabel}; | 5 | use ide_assists::{Assist, AssistId, AssistKind, AssistResolveStrategy, GroupLabel}; |
6 | use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; | 6 | use ide_db::{base_db::FileRange, label::Label, source_change::SourceChange, RootDatabase}; |
7 | 7 | ||
8 | pub(crate) fn add_ssr_assist( | 8 | pub(crate) fn ssr_assists( |
9 | db: &RootDatabase, | 9 | db: &RootDatabase, |
10 | base: &mut Vec<Assist>, | 10 | resolve: AssistResolveStrategy, |
11 | resolve: bool, | ||
12 | frange: FileRange, | 11 | frange: FileRange, |
13 | ) -> Option<()> { | 12 | ) -> Vec<Assist> { |
14 | let (match_finder, comment_range) = ide_ssr::ssr_from_comment(db, frange)?; | 13 | let mut ssr_assists = Vec::with_capacity(2); |
15 | 14 | ||
16 | let (source_change_for_file, source_change_for_workspace) = if resolve { | 15 | let (match_finder, comment_range) = match ide_ssr::ssr_from_comment(db, frange) { |
16 | Some((match_finder, comment_range)) => (match_finder, comment_range), | ||
17 | None => return ssr_assists, | ||
18 | }; | ||
19 | let id = AssistId("ssr", AssistKind::RefactorRewrite); | ||
20 | |||
21 | let (source_change_for_file, source_change_for_workspace) = if resolve.should_resolve(&id) { | ||
17 | let edits = match_finder.edits(); | 22 | let edits = match_finder.edits(); |
18 | 23 | ||
19 | let source_change_for_file = { | 24 | let source_change_for_file = { |
@@ -35,16 +40,17 @@ pub(crate) fn add_ssr_assist( | |||
35 | 40 | ||
36 | for (label, source_change) in assists.into_iter() { | 41 | for (label, source_change) in assists.into_iter() { |
37 | let assist = Assist { | 42 | let assist = Assist { |
38 | id: AssistId("ssr", AssistKind::RefactorRewrite), | 43 | id, |
39 | label: Label::new(label), | 44 | label: Label::new(label), |
40 | group: Some(GroupLabel("Apply SSR".into())), | 45 | group: Some(GroupLabel("Apply SSR".into())), |
41 | target: comment_range, | 46 | target: comment_range, |
42 | source_change, | 47 | source_change, |
43 | }; | 48 | }; |
44 | 49 | ||
45 | base.push(assist); | 50 | ssr_assists.push(assist); |
46 | } | 51 | } |
47 | Some(()) | 52 | |
53 | ssr_assists | ||
48 | } | 54 | } |
49 | 55 | ||
50 | #[cfg(test)] | 56 | #[cfg(test)] |
@@ -52,7 +58,7 @@ mod tests { | |||
52 | use std::sync::Arc; | 58 | use std::sync::Arc; |
53 | 59 | ||
54 | use expect_test::expect; | 60 | use expect_test::expect; |
55 | use ide_assists::Assist; | 61 | use ide_assists::{Assist, AssistResolveStrategy}; |
56 | use ide_db::{ | 62 | use ide_db::{ |
57 | base_db::{fixture::WithFixture, salsa::Durability, FileRange}, | 63 | base_db::{fixture::WithFixture, salsa::Durability, FileRange}, |
58 | symbol_index::SymbolsDatabase, | 64 | symbol_index::SymbolsDatabase, |
@@ -60,24 +66,14 @@ mod tests { | |||
60 | }; | 66 | }; |
61 | use rustc_hash::FxHashSet; | 67 | use rustc_hash::FxHashSet; |
62 | 68 | ||
63 | use super::add_ssr_assist; | 69 | use super::ssr_assists; |
64 | 70 | ||
65 | fn get_assists(ra_fixture: &str, resolve: bool) -> Vec<Assist> { | 71 | fn get_assists(ra_fixture: &str, resolve: AssistResolveStrategy) -> Vec<Assist> { |
66 | let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); | 72 | let (mut db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); |
67 | let mut local_roots = FxHashSet::default(); | 73 | let mut local_roots = FxHashSet::default(); |
68 | local_roots.insert(ide_db::base_db::fixture::WORKSPACE); | 74 | local_roots.insert(ide_db::base_db::fixture::WORKSPACE); |
69 | db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); | 75 | db.set_local_roots_with_durability(Arc::new(local_roots), Durability::HIGH); |
70 | 76 | ssr_assists(&db, resolve, FileRange { file_id, range: range_or_offset.into() }) | |
71 | let mut assists = vec![]; | ||
72 | |||
73 | add_ssr_assist( | ||
74 | &db, | ||
75 | &mut assists, | ||
76 | resolve, | ||
77 | FileRange { file_id, range: range_or_offset.into() }, | ||
78 | ); | ||
79 | |||
80 | assists | ||
81 | } | 77 | } |
82 | 78 | ||
83 | #[test] | 79 | #[test] |
@@ -88,16 +84,14 @@ mod tests { | |||
88 | // This is foo $0 | 84 | // This is foo $0 |
89 | fn foo() {} | 85 | fn foo() {} |
90 | "#; | 86 | "#; |
91 | let resolve = true; | 87 | let assists = get_assists(ra_fixture, AssistResolveStrategy::All); |
92 | |||
93 | let assists = get_assists(ra_fixture, resolve); | ||
94 | 88 | ||
95 | assert_eq!(0, assists.len()); | 89 | assert_eq!(0, assists.len()); |
96 | } | 90 | } |
97 | 91 | ||
92 | // TODO kb add partial resolve test | ||
98 | #[test] | 93 | #[test] |
99 | fn resolve_edits_true() { | 94 | fn resolve_edits_true() { |
100 | let resolve = true; | ||
101 | let assists = get_assists( | 95 | let assists = get_assists( |
102 | r#" | 96 | r#" |
103 | //- /lib.rs | 97 | //- /lib.rs |
@@ -109,7 +103,7 @@ mod tests { | |||
109 | //- /bar.rs | 103 | //- /bar.rs |
110 | fn bar() { 2 } | 104 | fn bar() { 2 } |
111 | "#, | 105 | "#, |
112 | resolve, | 106 | AssistResolveStrategy::All, |
113 | ); | 107 | ); |
114 | 108 | ||
115 | assert_eq!(2, assists.len()); | 109 | assert_eq!(2, assists.len()); |
@@ -200,7 +194,6 @@ mod tests { | |||
200 | 194 | ||
201 | #[test] | 195 | #[test] |
202 | fn resolve_edits_false() { | 196 | fn resolve_edits_false() { |
203 | let resolve = false; | ||
204 | let assists = get_assists( | 197 | let assists = get_assists( |
205 | r#" | 198 | r#" |
206 | //- /lib.rs | 199 | //- /lib.rs |
@@ -212,7 +205,7 @@ mod tests { | |||
212 | //- /bar.rs | 205 | //- /bar.rs |
213 | fn bar() { 2 } | 206 | fn bar() { 2 } |
214 | "#, | 207 | "#, |
215 | resolve, | 208 | AssistResolveStrategy::None, |
216 | ); | 209 | ); |
217 | 210 | ||
218 | assert_eq!(2, assists.len()); | 211 | assert_eq!(2, assists.len()); |