aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-08-18 17:40:12 +0100
committerGitHub <[email protected]>2020-08-18 17:40:12 +0100
commitaa2def023e6b0aa8a68f4992423f566d435e55c6 (patch)
tree769fbd88c0845367795e1273333245d2cadfc475 /crates/ide/src
parentf7a8ce35256e6a79dbe641787007e18a74e52b16 (diff)
parent8146669542dfc887956901b54a453c9a97fee7e3 (diff)
Merge #5804
5804: Add type safety to diagnostic codes r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ide/src')
-rw-r--r--crates/ide/src/diagnostics.rs76
1 files changed, 17 insertions, 59 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 3c36c0e15..92b5adaa2 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -25,7 +25,7 @@ use self::fixes::DiagnosticWithFix;
25 25
26#[derive(Debug)] 26#[derive(Debug)]
27pub struct Diagnostic { 27pub struct Diagnostic {
28 pub name: Option<String>, 28 // pub name: Option<String>,
29 pub message: String, 29 pub message: String,
30 pub range: TextRange, 30 pub range: TextRange,
31 pub severity: Severity, 31 pub severity: Severity,
@@ -71,7 +71,7 @@ pub(crate) fn diagnostics(
71 71
72 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. 72 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
73 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic { 73 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic {
74 name: None, 74 // name: None,
75 range: err.range(), 75 range: err.range(),
76 message: format!("Syntax Error: {}", err), 76 message: format!("Syntax Error: {}", err),
77 severity: Severity::Error, 77 severity: Severity::Error,
@@ -98,14 +98,14 @@ pub(crate) fn diagnostics(
98 }) 98 })
99 // Only collect experimental diagnostics when they're enabled. 99 // Only collect experimental diagnostics when they're enabled.
100 .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) 100 .filter(|diag| !(diag.is_experimental() && config.disable_experimental))
101 .filter(|diag| !config.disabled.contains(diag.name())); 101 .filter(|diag| !config.disabled.contains(diag.code().as_str()));
102 102
103 // Finalize the `DiagnosticSink` building process. 103 // Finalize the `DiagnosticSink` building process.
104 let mut sink = sink_builder 104 let mut sink = sink_builder
105 // Diagnostics not handled above get no fix and default treatment. 105 // Diagnostics not handled above get no fix and default treatment.
106 .build(|d| { 106 .build(|d| {
107 res.borrow_mut().push(Diagnostic { 107 res.borrow_mut().push(Diagnostic {
108 name: Some(d.name().into()), 108 // name: Some(d.name().into()),
109 message: d.message(), 109 message: d.message(),
110 range: sema.diagnostics_display_range(d).range, 110 range: sema.diagnostics_display_range(d).range,
111 severity: Severity::Error, 111 severity: Severity::Error,
@@ -122,7 +122,7 @@ pub(crate) fn diagnostics(
122 122
123fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { 123fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic {
124 Diagnostic { 124 Diagnostic {
125 name: Some(d.name().into()), 125 // name: Some(d.name().into()),
126 range: sema.diagnostics_display_range(d).range, 126 range: sema.diagnostics_display_range(d).range,
127 message: d.message(), 127 message: d.message(),
128 severity: Severity::Error, 128 severity: Severity::Error,
@@ -149,7 +149,7 @@ fn check_unnecessary_braces_in_use_statement(
149 }); 149 });
150 150
151 acc.push(Diagnostic { 151 acc.push(Diagnostic {
152 name: None, 152 // name: None,
153 range: use_range, 153 range: use_range,
154 message: "Unnecessary braces in use statement".to_string(), 154 message: "Unnecessary braces in use statement".to_string(),
155 severity: Severity::WeakWarning, 155 severity: Severity::WeakWarning,
@@ -196,7 +196,7 @@ fn check_struct_shorthand_initialization(
196 196
197 let field_range = record_field.syntax().text_range(); 197 let field_range = record_field.syntax().text_range();
198 acc.push(Diagnostic { 198 acc.push(Diagnostic {
199 name: None, 199 // name: None,
200 range: field_range, 200 range: field_range,
201 message: "Shorthand struct initialization".to_string(), 201 message: "Shorthand struct initialization".to_string(),
202 severity: Severity::WeakWarning, 202 severity: Severity::WeakWarning,
@@ -294,54 +294,6 @@ mod tests {
294 assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); 294 assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics);
295 } 295 }
296 296
297 /// Takes a multi-file input fixture with annotated cursor position and the list of disabled diagnostics,
298 /// and checks that provided diagnostics aren't spawned during analysis.
299 fn check_disabled_diagnostics(ra_fixture: &str, disabled_diagnostics: &[&'static str]) {
300 let mut config = DiagnosticsConfig::default();
301 config.disabled = disabled_diagnostics.into_iter().map(|diag| diag.to_string()).collect();
302
303 let mock = MockAnalysis::with_files(ra_fixture);
304 let files = mock.files().map(|(it, _)| it).collect::<Vec<_>>();
305 let analysis = mock.analysis();
306
307 let diagnostics = files
308 .clone()
309 .into_iter()
310 .flat_map(|file_id| analysis.diagnostics(&config, file_id).unwrap())
311 .collect::<Vec<_>>();
312
313 // First, we have to check that diagnostic is not emitted when it's added to the disabled diagnostics list.
314 for diagnostic in diagnostics {
315 if let Some(name) = diagnostic.name {
316 assert!(
317 !disabled_diagnostics.contains(&name.as_str()),
318 "Diagnostic {} is disabled",
319 name
320 );
321 }
322 }
323
324 // Then, we must reset the config and repeat the check, so that we'll be sure that without
325 // config these diagnostics are emitted.
326 // This is required for tests to not become outdated if e.g. diagnostics name changes:
327 // without this additional run the test will pass simply because a diagnostic with an old name
328 // will no longer exist.
329 let diagnostics = files
330 .into_iter()
331 .flat_map(|file_id| {
332 analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap()
333 })
334 .collect::<Vec<_>>();
335
336 assert!(
337 diagnostics
338 .into_iter()
339 .filter_map(|diag| diag.name)
340 .any(|name| disabled_diagnostics.contains(&name.as_str())),
341 "At least one of the diagnostics was not emitted even without config; are the diagnostics names correct?"
342 );
343 }
344
345 fn check_expect(ra_fixture: &str, expect: Expect) { 297 fn check_expect(ra_fixture: &str, expect: Expect) {
346 let (analysis, file_id) = single_file(ra_fixture); 298 let (analysis, file_id) = single_file(ra_fixture);
347 let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap(); 299 let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap();
@@ -604,9 +556,6 @@ fn test_fn() {
604 expect![[r#" 556 expect![[r#"
605 [ 557 [
606 Diagnostic { 558 Diagnostic {
607 name: Some(
608 "unresolved-module",
609 ),
610 message: "unresolved module", 559 message: "unresolved module",
611 range: 0..8, 560 range: 0..8,
612 severity: Error, 561 severity: Error,
@@ -783,6 +732,15 @@ struct Foo {
783 732
784 #[test] 733 #[test]
785 fn test_disabled_diagnostics() { 734 fn test_disabled_diagnostics() {
786 check_disabled_diagnostics(r#"mod foo;"#, &["unresolved-module"]); 735 let mut config = DiagnosticsConfig::default();
736 config.disabled.insert("unresolved-module".into());
737
738 let (analysis, file_id) = single_file(r#"mod foo;"#);
739
740 let diagnostics = analysis.diagnostics(&config, file_id).unwrap();
741 assert!(diagnostics.is_empty());
742
743 let diagnostics = analysis.diagnostics(&DiagnosticsConfig::default(), file_id).unwrap();
744 assert!(!diagnostics.is_empty());
787 } 745 }
788} 746}