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.rs | |
parent | 04b5fcfdb28f18f4d5279b43c2bb2b3f9c082313 (diff) |
feat: improve performance by delaying computation of fixes for diagnostics
Diffstat (limited to 'crates/ide/src/diagnostics.rs')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 4f0b4a62e..9a883acb9 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -84,6 +84,7 @@ pub struct DiagnosticsConfig { | |||
84 | pub(crate) fn diagnostics( | 84 | pub(crate) fn diagnostics( |
85 | db: &RootDatabase, | 85 | db: &RootDatabase, |
86 | config: &DiagnosticsConfig, | 86 | config: &DiagnosticsConfig, |
87 | resolve: bool, | ||
87 | file_id: FileId, | 88 | file_id: FileId, |
88 | ) -> Vec<Diagnostic> { | 89 | ) -> Vec<Diagnostic> { |
89 | let _p = profile::span("diagnostics"); | 90 | let _p = profile::span("diagnostics"); |
@@ -107,25 +108,25 @@ pub(crate) fn diagnostics( | |||
107 | let res = RefCell::new(res); | 108 | let res = RefCell::new(res); |
108 | let sink_builder = DiagnosticSinkBuilder::new() | 109 | let sink_builder = DiagnosticSinkBuilder::new() |
109 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 110 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
110 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 111 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); |
111 | }) | 112 | }) |
112 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 113 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
113 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 114 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); |
114 | }) | 115 | }) |
115 | .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| { | 116 | .on::<hir::diagnostics::MissingOkOrSomeInTailExpr, _>(|d| { |
116 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 117 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); |
117 | }) | 118 | }) |
118 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 119 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
119 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 120 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); |
120 | }) | 121 | }) |
121 | .on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| { | 122 | .on::<hir::diagnostics::RemoveThisSemicolon, _>(|d| { |
122 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 123 | res.borrow_mut().push(diagnostic_with_fix(d, &sema, resolve)); |
123 | }) | 124 | }) |
124 | .on::<hir::diagnostics::IncorrectCase, _>(|d| { | 125 | .on::<hir::diagnostics::IncorrectCase, _>(|d| { |
125 | res.borrow_mut().push(warning_with_fix(d, &sema)); | 126 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); |
126 | }) | 127 | }) |
127 | .on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| { | 128 | .on::<hir::diagnostics::ReplaceFilterMapNextWithFindMap, _>(|d| { |
128 | res.borrow_mut().push(warning_with_fix(d, &sema)); | 129 | res.borrow_mut().push(warning_with_fix(d, &sema, resolve)); |
129 | }) | 130 | }) |
130 | .on::<hir::diagnostics::InactiveCode, _>(|d| { | 131 | .on::<hir::diagnostics::InactiveCode, _>(|d| { |
131 | // If there's inactive code somewhere in a macro, don't propagate to the call-site. | 132 | // If there's inactive code somewhere in a macro, don't propagate to the call-site. |
@@ -152,7 +153,7 @@ pub(crate) fn diagnostics( | |||
152 | // Override severity and mark as unused. | 153 | // Override severity and mark as unused. |
153 | res.borrow_mut().push( | 154 | res.borrow_mut().push( |
154 | Diagnostic::hint(range, d.message()) | 155 | Diagnostic::hint(range, d.message()) |
155 | .with_fix(d.fix(&sema)) | 156 | .with_fix(d.fix(&sema, resolve)) |
156 | .with_code(Some(d.code())), | 157 | .with_code(Some(d.code())), |
157 | ); | 158 | ); |
158 | }) | 159 | }) |
@@ -208,15 +209,23 @@ pub(crate) fn diagnostics( | |||
208 | res.into_inner() | 209 | res.into_inner() |
209 | } | 210 | } |
210 | 211 | ||
211 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { | 212 | fn diagnostic_with_fix<D: DiagnosticWithFix>( |
213 | d: &D, | ||
214 | sema: &Semantics<RootDatabase>, | ||
215 | resolve: bool, | ||
216 | ) -> Diagnostic { | ||
212 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) | 217 | Diagnostic::error(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
213 | .with_fix(d.fix(&sema)) | 218 | .with_fix(d.fix(&sema, resolve)) |
214 | .with_code(Some(d.code())) | 219 | .with_code(Some(d.code())) |
215 | } | 220 | } |
216 | 221 | ||
217 | fn warning_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { | 222 | fn warning_with_fix<D: DiagnosticWithFix>( |
223 | d: &D, | ||
224 | sema: &Semantics<RootDatabase>, | ||
225 | resolve: bool, | ||
226 | ) -> Diagnostic { | ||
218 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) | 227 | Diagnostic::hint(sema.diagnostics_display_range(d.display_source()).range, d.message()) |
219 | .with_fix(d.fix(&sema)) | 228 | .with_fix(d.fix(&sema, resolve)) |
220 | .with_code(Some(d.code())) | 229 | .with_code(Some(d.code())) |
221 | } | 230 | } |
222 | 231 | ||
@@ -271,13 +280,19 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement( | |||
271 | } | 280 | } |
272 | 281 | ||
273 | fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextRange) -> Assist { | 282 | fn fix(id: &'static str, label: &str, source_change: SourceChange, target: TextRange) -> Assist { |
283 | let mut res = unresolved_fix(id, label, target); | ||
284 | res.source_change = Some(source_change); | ||
285 | res | ||
286 | } | ||
287 | |||
288 | fn unresolved_fix(id: &'static str, label: &str, target: TextRange) -> Assist { | ||
274 | assert!(!id.contains(' ')); | 289 | assert!(!id.contains(' ')); |
275 | Assist { | 290 | Assist { |
276 | id: AssistId(id, AssistKind::QuickFix), | 291 | id: AssistId(id, AssistKind::QuickFix), |
277 | label: Label::new(label), | 292 | label: Label::new(label), |
278 | group: None, | 293 | group: None, |
279 | target, | 294 | target, |
280 | source_change: Some(source_change), | 295 | source_change: None, |
281 | } | 296 | } |
282 | } | 297 | } |
283 | 298 | ||
@@ -299,7 +314,7 @@ mod tests { | |||
299 | 314 | ||
300 | let (analysis, file_position) = fixture::position(ra_fixture_before); | 315 | let (analysis, file_position) = fixture::position(ra_fixture_before); |
301 | let diagnostic = analysis | 316 | let diagnostic = analysis |
302 | .diagnostics(&DiagnosticsConfig::default(), file_position.file_id) | 317 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) |
303 | .unwrap() | 318 | .unwrap() |
304 | .pop() | 319 | .pop() |
305 | .unwrap(); | 320 | .unwrap(); |
@@ -328,7 +343,7 @@ mod tests { | |||
328 | fn check_no_fix(ra_fixture: &str) { | 343 | fn check_no_fix(ra_fixture: &str) { |
329 | let (analysis, file_position) = fixture::position(ra_fixture); | 344 | let (analysis, file_position) = fixture::position(ra_fixture); |
330 | let diagnostic = analysis | 345 | let diagnostic = analysis |
331 | .diagnostics(&DiagnosticsConfig::default(), file_position.file_id) | 346 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) |
332 | .unwrap() | 347 | .unwrap() |
333 | .pop() | 348 | .pop() |
334 | .unwrap(); | 349 | .unwrap(); |
@@ -342,7 +357,7 @@ mod tests { | |||
342 | let diagnostics = files | 357 | let diagnostics = files |
343 | .into_iter() | 358 | .into_iter() |
344 | .flat_map(|file_id| { | 359 | .flat_map(|file_id| { |
345 | analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap() | 360 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap() |
346 | }) | 361 | }) |
347 | .collect::<Vec<_>>(); | 362 | .collect::<Vec<_>>(); |
348 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | 363 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); |
@@ -350,7 +365,8 @@ mod tests { | |||
350 | 365 | ||
351 | fn check_expect(ra_fixture: &str, expect: Expect) { | 366 | fn check_expect(ra_fixture: &str, expect: Expect) { |
352 | let (analysis, file_id) = fixture::file(ra_fixture); | 367 | let (analysis, file_id) = fixture::file(ra_fixture); |
353 | let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap(); | 368 | let diagnostics = |
369 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap(); | ||
354 | expect.assert_debug_eq(&diagnostics) | 370 | expect.assert_debug_eq(&diagnostics) |
355 | } | 371 | } |
356 | 372 | ||
@@ -895,10 +911,11 @@ struct Foo { | |||
895 | 911 | ||
896 | let (analysis, file_id) = fixture::file(r#"mod foo;"#); | 912 | let (analysis, file_id) = fixture::file(r#"mod foo;"#); |
897 | 913 | ||
898 | let diagnostics = analysis.diagnostics(&config, file_id).unwrap(); | 914 | let diagnostics = analysis.diagnostics(&config, true, file_id).unwrap(); |
899 | assert!(diagnostics.is_empty()); | 915 | assert!(diagnostics.is_empty()); |
900 | 916 | ||
901 | let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap(); | 917 | let diagnostics = |
918 | analysis.diagnostics(&DiagnosticsConfig::default(), true, file_id).unwrap(); | ||
902 | assert!(!diagnostics.is_empty()); | 919 | assert!(!diagnostics.is_empty()); |
903 | } | 920 | } |
904 | 921 | ||
@@ -1004,8 +1021,9 @@ impl TestStruct { | |||
1004 | let expected = r#"fn foo() {}"#; | 1021 | let expected = r#"fn foo() {}"#; |
1005 | 1022 | ||
1006 | let (analysis, file_position) = fixture::position(input); | 1023 | let (analysis, file_position) = fixture::position(input); |
1007 | let diagnostics = | 1024 | let diagnostics = analysis |
1008 | analysis.diagnostics(&DiagnosticsConfig::default(), file_position.file_id).unwrap(); | 1025 | .diagnostics(&DiagnosticsConfig::default(), true, file_position.file_id) |
1026 | .unwrap(); | ||
1009 | assert_eq!(diagnostics.len(), 1); | 1027 | assert_eq!(diagnostics.len(), 1); |
1010 | 1028 | ||
1011 | check_fix(input, expected); | 1029 | check_fix(input, expected); |