diff options
-rw-r--r-- | crates/hir_def/src/diagnostics.rs | 3 | ||||
-rw-r--r-- | crates/hir_expand/src/diagnostics.rs | 1 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics.rs | 25 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 82 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 10 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/analysis_bench.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/cli/diagnostics.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 24 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 12 | ||||
-rw-r--r-- | editors/code/package.json | 9 |
10 files changed, 155 insertions, 15 deletions
diff --git a/crates/hir_def/src/diagnostics.rs b/crates/hir_def/src/diagnostics.rs index 2e38a978f..c7723de00 100644 --- a/crates/hir_def/src/diagnostics.rs +++ b/crates/hir_def/src/diagnostics.rs | |||
@@ -15,6 +15,9 @@ pub struct UnresolvedModule { | |||
15 | } | 15 | } |
16 | 16 | ||
17 | impl Diagnostic for UnresolvedModule { | 17 | impl Diagnostic for UnresolvedModule { |
18 | fn name(&self) -> &'static str { | ||
19 | "unresolved-module" | ||
20 | } | ||
18 | fn message(&self) -> String { | 21 | fn message(&self) -> String { |
19 | "unresolved module".to_string() | 22 | "unresolved module".to_string() |
20 | } | 23 | } |
diff --git a/crates/hir_expand/src/diagnostics.rs b/crates/hir_expand/src/diagnostics.rs index 59d35debe..6c81b2501 100644 --- a/crates/hir_expand/src/diagnostics.rs +++ b/crates/hir_expand/src/diagnostics.rs | |||
@@ -21,6 +21,7 @@ use syntax::SyntaxNodePtr; | |||
21 | use crate::InFile; | 21 | use crate::InFile; |
22 | 22 | ||
23 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 23 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { |
24 | fn name(&self) -> &'static str; | ||
24 | fn message(&self) -> String; | 25 | fn message(&self) -> String; |
25 | /// Used in highlighting and related purposes | 26 | /// Used in highlighting and related purposes |
26 | fn display_source(&self) -> InFile<SyntaxNodePtr>; | 27 | fn display_source(&self) -> InFile<SyntaxNodePtr>; |
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs index ae0cf8d09..38fa24ee0 100644 --- a/crates/hir_ty/src/diagnostics.rs +++ b/crates/hir_ty/src/diagnostics.rs | |||
@@ -32,6 +32,10 @@ pub struct NoSuchField { | |||
32 | } | 32 | } |
33 | 33 | ||
34 | impl Diagnostic for NoSuchField { | 34 | impl Diagnostic for NoSuchField { |
35 | fn name(&self) -> &'static str { | ||
36 | "no-such-field" | ||
37 | } | ||
38 | |||
35 | fn message(&self) -> String { | 39 | fn message(&self) -> String { |
36 | "no such field".to_string() | 40 | "no such field".to_string() |
37 | } | 41 | } |
@@ -54,6 +58,9 @@ pub struct MissingFields { | |||
54 | } | 58 | } |
55 | 59 | ||
56 | impl Diagnostic for MissingFields { | 60 | impl Diagnostic for MissingFields { |
61 | fn name(&self) -> &'static str { | ||
62 | "missing-structure-fields" | ||
63 | } | ||
57 | fn message(&self) -> String { | 64 | fn message(&self) -> String { |
58 | let mut buf = String::from("Missing structure fields:\n"); | 65 | let mut buf = String::from("Missing structure fields:\n"); |
59 | for field in &self.missed_fields { | 66 | for field in &self.missed_fields { |
@@ -87,6 +94,9 @@ pub struct MissingPatFields { | |||
87 | } | 94 | } |
88 | 95 | ||
89 | impl Diagnostic for MissingPatFields { | 96 | impl Diagnostic for MissingPatFields { |
97 | fn name(&self) -> &'static str { | ||
98 | "missing-pat-fields" | ||
99 | } | ||
90 | fn message(&self) -> String { | 100 | fn message(&self) -> String { |
91 | let mut buf = String::from("Missing structure fields:\n"); | 101 | let mut buf = String::from("Missing structure fields:\n"); |
92 | for field in &self.missed_fields { | 102 | for field in &self.missed_fields { |
@@ -117,6 +127,9 @@ pub struct MissingMatchArms { | |||
117 | } | 127 | } |
118 | 128 | ||
119 | impl Diagnostic for MissingMatchArms { | 129 | impl Diagnostic for MissingMatchArms { |
130 | fn name(&self) -> &'static str { | ||
131 | "missing-match-arm" | ||
132 | } | ||
120 | fn message(&self) -> String { | 133 | fn message(&self) -> String { |
121 | String::from("Missing match arm") | 134 | String::from("Missing match arm") |
122 | } | 135 | } |
@@ -135,6 +148,9 @@ pub struct MissingOkInTailExpr { | |||
135 | } | 148 | } |
136 | 149 | ||
137 | impl Diagnostic for MissingOkInTailExpr { | 150 | impl Diagnostic for MissingOkInTailExpr { |
151 | fn name(&self) -> &'static str { | ||
152 | "missing-ok-in-tail-expr" | ||
153 | } | ||
138 | fn message(&self) -> String { | 154 | fn message(&self) -> String { |
139 | "wrap return expression in Ok".to_string() | 155 | "wrap return expression in Ok".to_string() |
140 | } | 156 | } |
@@ -153,6 +169,9 @@ pub struct BreakOutsideOfLoop { | |||
153 | } | 169 | } |
154 | 170 | ||
155 | impl Diagnostic for BreakOutsideOfLoop { | 171 | impl Diagnostic for BreakOutsideOfLoop { |
172 | fn name(&self) -> &'static str { | ||
173 | "break-outside-of-loop" | ||
174 | } | ||
156 | fn message(&self) -> String { | 175 | fn message(&self) -> String { |
157 | "break outside of loop".to_string() | 176 | "break outside of loop".to_string() |
158 | } | 177 | } |
@@ -171,6 +190,9 @@ pub struct MissingUnsafe { | |||
171 | } | 190 | } |
172 | 191 | ||
173 | impl Diagnostic for MissingUnsafe { | 192 | impl Diagnostic for MissingUnsafe { |
193 | fn name(&self) -> &'static str { | ||
194 | "missing-unsafe" | ||
195 | } | ||
174 | fn message(&self) -> String { | 196 | fn message(&self) -> String { |
175 | format!("This operation is unsafe and requires an unsafe function or block") | 197 | format!("This operation is unsafe and requires an unsafe function or block") |
176 | } | 198 | } |
@@ -191,6 +213,9 @@ pub struct MismatchedArgCount { | |||
191 | } | 213 | } |
192 | 214 | ||
193 | impl Diagnostic for MismatchedArgCount { | 215 | impl Diagnostic for MismatchedArgCount { |
216 | fn name(&self) -> &'static str { | ||
217 | "mismatched-arg-count" | ||
218 | } | ||
194 | fn message(&self) -> String { | 219 | fn message(&self) -> String { |
195 | let s = if self.expected == 1 { "" } else { "s" }; | 220 | let s = if self.expected == 1 { "" } else { "s" }; |
196 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) | 221 | format!("Expected {} argument{}, found {}", self.expected, s, self.found) |
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index a3ec98178..606a6064b 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -4,7 +4,7 @@ | |||
4 | //! macro-expanded files, but we need to present them to the users in terms of | 4 | //! macro-expanded files, but we need to present them to the users in terms of |
5 | //! original files. So we need to map the ranges. | 5 | //! original files. So we need to map the ranges. |
6 | 6 | ||
7 | use std::cell::RefCell; | 7 | use std::{cell::RefCell, collections::HashSet}; |
8 | 8 | ||
9 | use base_db::SourceDatabase; | 9 | use base_db::SourceDatabase; |
10 | use hir::{diagnostics::DiagnosticSinkBuilder, Semantics}; | 10 | use hir::{diagnostics::DiagnosticSinkBuilder, Semantics}; |
@@ -31,6 +31,7 @@ pub(crate) fn diagnostics( | |||
31 | db: &RootDatabase, | 31 | db: &RootDatabase, |
32 | file_id: FileId, | 32 | file_id: FileId, |
33 | enable_experimental: bool, | 33 | enable_experimental: bool, |
34 | disabled_diagnostics: Option<HashSet<String>>, | ||
34 | ) -> Vec<Diagnostic> { | 35 | ) -> Vec<Diagnostic> { |
35 | let _p = profile::span("diagnostics"); | 36 | let _p = profile::span("diagnostics"); |
36 | let sema = Semantics::new(db); | 37 | let sema = Semantics::new(db); |
@@ -39,6 +40,7 @@ pub(crate) fn diagnostics( | |||
39 | 40 | ||
40 | // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. | 41 | // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. |
41 | res.extend(parse.errors().iter().take(128).map(|err| Diagnostic { | 42 | res.extend(parse.errors().iter().take(128).map(|err| Diagnostic { |
43 | name: None, | ||
42 | range: err.range(), | 44 | range: err.range(), |
43 | message: format!("Syntax Error: {}", err), | 45 | message: format!("Syntax Error: {}", err), |
44 | severity: Severity::Error, | 46 | severity: Severity::Error, |
@@ -50,7 +52,7 @@ pub(crate) fn diagnostics( | |||
50 | check_struct_shorthand_initialization(&mut res, file_id, &node); | 52 | check_struct_shorthand_initialization(&mut res, file_id, &node); |
51 | } | 53 | } |
52 | let res = RefCell::new(res); | 54 | let res = RefCell::new(res); |
53 | let mut sink = DiagnosticSinkBuilder::new() | 55 | let mut sink_builder = DiagnosticSinkBuilder::new() |
54 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 56 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
55 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 57 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
56 | }) | 58 | }) |
@@ -64,10 +66,19 @@ pub(crate) fn diagnostics( | |||
64 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); | 66 | res.borrow_mut().push(diagnostic_with_fix(d, &sema)); |
65 | }) | 67 | }) |
66 | // Only collect experimental diagnostics when they're enabled. | 68 | // Only collect experimental diagnostics when they're enabled. |
67 | .filter(|diag| !diag.is_experimental() || enable_experimental) | 69 | .filter(|diag| !diag.is_experimental() || enable_experimental); |
70 | |||
71 | if let Some(disabled_diagnostics) = disabled_diagnostics { | ||
72 | // Do not collect disabled diagnostics. | ||
73 | sink_builder = sink_builder.filter(move |diag| !disabled_diagnostics.contains(diag.name())); | ||
74 | } | ||
75 | |||
76 | // Finalize the `DiagnosticSink` building process. | ||
77 | let mut sink = sink_builder | ||
68 | // Diagnostics not handled above get no fix and default treatment. | 78 | // Diagnostics not handled above get no fix and default treatment. |
69 | .build(|d| { | 79 | .build(|d| { |
70 | res.borrow_mut().push(Diagnostic { | 80 | res.borrow_mut().push(Diagnostic { |
81 | name: Some(d.name().into()), | ||
71 | message: d.message(), | 82 | message: d.message(), |
72 | range: sema.diagnostics_display_range(d).range, | 83 | range: sema.diagnostics_display_range(d).range, |
73 | severity: Severity::Error, | 84 | severity: Severity::Error, |
@@ -84,6 +95,7 @@ pub(crate) fn diagnostics( | |||
84 | 95 | ||
85 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { | 96 | fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { |
86 | Diagnostic { | 97 | Diagnostic { |
98 | name: Some(d.name().into()), | ||
87 | range: sema.diagnostics_display_range(d).range, | 99 | range: sema.diagnostics_display_range(d).range, |
88 | message: d.message(), | 100 | message: d.message(), |
89 | severity: Severity::Error, | 101 | severity: Severity::Error, |
@@ -110,6 +122,7 @@ fn check_unnecessary_braces_in_use_statement( | |||
110 | }); | 122 | }); |
111 | 123 | ||
112 | acc.push(Diagnostic { | 124 | acc.push(Diagnostic { |
125 | name: None, | ||
113 | range: use_range, | 126 | range: use_range, |
114 | message: "Unnecessary braces in use statement".to_string(), | 127 | message: "Unnecessary braces in use statement".to_string(), |
115 | severity: Severity::WeakWarning, | 128 | severity: Severity::WeakWarning, |
@@ -156,6 +169,7 @@ fn check_struct_shorthand_initialization( | |||
156 | 169 | ||
157 | let field_range = record_field.syntax().text_range(); | 170 | let field_range = record_field.syntax().text_range(); |
158 | acc.push(Diagnostic { | 171 | acc.push(Diagnostic { |
172 | name: None, | ||
159 | range: field_range, | 173 | range: field_range, |
160 | message: "Shorthand struct initialization".to_string(), | 174 | message: "Shorthand struct initialization".to_string(), |
161 | severity: Severity::WeakWarning, | 175 | severity: Severity::WeakWarning, |
@@ -173,6 +187,7 @@ fn check_struct_shorthand_initialization( | |||
173 | 187 | ||
174 | #[cfg(test)] | 188 | #[cfg(test)] |
175 | mod tests { | 189 | mod tests { |
190 | use std::collections::HashSet; | ||
176 | use stdx::trim_indent; | 191 | use stdx::trim_indent; |
177 | use test_utils::assert_eq_text; | 192 | use test_utils::assert_eq_text; |
178 | 193 | ||
@@ -188,7 +203,8 @@ mod tests { | |||
188 | let after = trim_indent(ra_fixture_after); | 203 | let after = trim_indent(ra_fixture_after); |
189 | 204 | ||
190 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); | 205 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); |
191 | let diagnostic = analysis.diagnostics(file_position.file_id, true).unwrap().pop().unwrap(); | 206 | let diagnostic = |
207 | analysis.diagnostics(file_position.file_id, true, None).unwrap().pop().unwrap(); | ||
192 | let mut fix = diagnostic.fix.unwrap(); | 208 | let mut fix = diagnostic.fix.unwrap(); |
193 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | 209 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
194 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | 210 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); |
@@ -214,7 +230,7 @@ mod tests { | |||
214 | let ra_fixture_after = &trim_indent(ra_fixture_after); | 230 | let ra_fixture_after = &trim_indent(ra_fixture_after); |
215 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); | 231 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); |
216 | let current_file_id = file_pos.file_id; | 232 | let current_file_id = file_pos.file_id; |
217 | let diagnostic = analysis.diagnostics(current_file_id, true).unwrap().pop().unwrap(); | 233 | let diagnostic = analysis.diagnostics(current_file_id, true, None).unwrap().pop().unwrap(); |
218 | let mut fix = diagnostic.fix.unwrap(); | 234 | let mut fix = diagnostic.fix.unwrap(); |
219 | let edit = fix.source_change.source_file_edits.pop().unwrap(); | 235 | let edit = fix.source_change.source_file_edits.pop().unwrap(); |
220 | let changed_file_id = edit.file_id; | 236 | let changed_file_id = edit.file_id; |
@@ -235,14 +251,58 @@ mod tests { | |||
235 | let analysis = mock.analysis(); | 251 | let analysis = mock.analysis(); |
236 | let diagnostics = files | 252 | let diagnostics = files |
237 | .into_iter() | 253 | .into_iter() |
238 | .flat_map(|file_id| analysis.diagnostics(file_id, true).unwrap()) | 254 | .flat_map(|file_id| analysis.diagnostics(file_id, true, None).unwrap()) |
239 | .collect::<Vec<_>>(); | 255 | .collect::<Vec<_>>(); |
240 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | 256 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); |
241 | } | 257 | } |
242 | 258 | ||
259 | /// Takes a multi-file input fixture with annotated cursor position and the list of disabled diagnostics, | ||
260 | /// and checks that provided diagnostics aren't spawned during analysis. | ||
261 | fn check_disabled_diagnostics(ra_fixture: &str, disabled_diagnostics: &[&'static str]) { | ||
262 | let disabled_diagnostics: HashSet<_> = | ||
263 | disabled_diagnostics.into_iter().map(|diag| diag.to_string()).collect(); | ||
264 | |||
265 | let mock = MockAnalysis::with_files(ra_fixture); | ||
266 | let files = mock.files().map(|(it, _)| it).collect::<Vec<_>>(); | ||
267 | let analysis = mock.analysis(); | ||
268 | |||
269 | let diagnostics = files | ||
270 | .clone() | ||
271 | .into_iter() | ||
272 | .flat_map(|file_id| { | ||
273 | analysis.diagnostics(file_id, true, Some(disabled_diagnostics.clone())).unwrap() | ||
274 | }) | ||
275 | .collect::<Vec<_>>(); | ||
276 | |||
277 | // First, we have to check that diagnostic is not emitted when it's added to the disabled diagnostics list. | ||
278 | for diagnostic in diagnostics { | ||
279 | if let Some(name) = diagnostic.name { | ||
280 | assert!(!disabled_diagnostics.contains(&name), "Diagnostic {} is disabled", name); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | // Then, we must reset the config and repeat the check, so that we'll be sure that without | ||
285 | // config these diagnostics are emitted. | ||
286 | // This is required for tests to not become outdated if e.g. diagnostics name changes: | ||
287 | // without this additional run the test will pass simply because a diagnostic with an old name | ||
288 | // will no longer exist. | ||
289 | let diagnostics = files | ||
290 | .into_iter() | ||
291 | .flat_map(|file_id| analysis.diagnostics(file_id, true, None).unwrap()) | ||
292 | .collect::<Vec<_>>(); | ||
293 | |||
294 | assert!( | ||
295 | diagnostics | ||
296 | .into_iter() | ||
297 | .filter_map(|diag| diag.name) | ||
298 | .any(|name| disabled_diagnostics.contains(&name)), | ||
299 | "At least one of the diagnostics was not emitted even without config; are the diagnostics names correct?" | ||
300 | ); | ||
301 | } | ||
302 | |||
243 | fn check_expect(ra_fixture: &str, expect: Expect) { | 303 | fn check_expect(ra_fixture: &str, expect: Expect) { |
244 | let (analysis, file_id) = single_file(ra_fixture); | 304 | let (analysis, file_id) = single_file(ra_fixture); |
245 | let diagnostics = analysis.diagnostics(file_id, true).unwrap(); | 305 | let diagnostics = analysis.diagnostics(file_id, true, None).unwrap(); |
246 | expect.assert_debug_eq(&diagnostics) | 306 | expect.assert_debug_eq(&diagnostics) |
247 | } | 307 | } |
248 | 308 | ||
@@ -502,6 +562,9 @@ fn test_fn() { | |||
502 | expect![[r#" | 562 | expect![[r#" |
503 | [ | 563 | [ |
504 | Diagnostic { | 564 | Diagnostic { |
565 | name: Some( | ||
566 | "unresolved-module", | ||
567 | ), | ||
505 | message: "unresolved module", | 568 | message: "unresolved module", |
506 | range: 0..8, | 569 | range: 0..8, |
507 | severity: Error, | 570 | severity: Error, |
@@ -675,4 +738,9 @@ struct Foo { | |||
675 | ", | 738 | ", |
676 | ) | 739 | ) |
677 | } | 740 | } |
741 | |||
742 | #[test] | ||
743 | fn test_disabled_diagnostics() { | ||
744 | check_disabled_diagnostics(r#"mod foo;"#, &["unresolved-module"]); | ||
745 | } | ||
678 | } | 746 | } |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index eb6389529..4b797f374 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -44,7 +44,7 @@ mod syntax_highlighting; | |||
44 | mod syntax_tree; | 44 | mod syntax_tree; |
45 | mod typing; | 45 | mod typing; |
46 | 46 | ||
47 | use std::sync::Arc; | 47 | use std::{collections::HashSet, sync::Arc}; |
48 | 48 | ||
49 | use base_db::{ | 49 | use base_db::{ |
50 | salsa::{self, ParallelDatabase}, | 50 | salsa::{self, ParallelDatabase}, |
@@ -101,6 +101,7 @@ pub type Cancelable<T> = Result<T, Canceled>; | |||
101 | 101 | ||
102 | #[derive(Debug)] | 102 | #[derive(Debug)] |
103 | pub struct Diagnostic { | 103 | pub struct Diagnostic { |
104 | pub name: Option<String>, | ||
104 | pub message: String, | 105 | pub message: String, |
105 | pub range: TextRange, | 106 | pub range: TextRange, |
106 | pub severity: Severity, | 107 | pub severity: Severity, |
@@ -147,7 +148,7 @@ pub struct AnalysisHost { | |||
147 | } | 148 | } |
148 | 149 | ||
149 | impl AnalysisHost { | 150 | impl AnalysisHost { |
150 | pub fn new(lru_capacity: Option<usize>) -> AnalysisHost { | 151 | pub fn new(lru_capacity: Option<usize>) -> Self { |
151 | AnalysisHost { db: RootDatabase::new(lru_capacity) } | 152 | AnalysisHost { db: RootDatabase::new(lru_capacity) } |
152 | } | 153 | } |
153 | 154 | ||
@@ -496,8 +497,11 @@ impl Analysis { | |||
496 | &self, | 497 | &self, |
497 | file_id: FileId, | 498 | file_id: FileId, |
498 | enable_experimental: bool, | 499 | enable_experimental: bool, |
500 | disabled_diagnostics: Option<HashSet<String>>, | ||
499 | ) -> Cancelable<Vec<Diagnostic>> { | 501 | ) -> Cancelable<Vec<Diagnostic>> { |
500 | self.with_db(|db| diagnostics::diagnostics(db, file_id, enable_experimental)) | 502 | self.with_db(|db| { |
503 | diagnostics::diagnostics(db, file_id, enable_experimental, disabled_diagnostics) | ||
504 | }) | ||
501 | } | 505 | } |
502 | 506 | ||
503 | /// Returns the edit required to rename reference at the position to the new | 507 | /// Returns the edit required to rename reference at the position to the new |
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs index 0f614f9e0..43f0196af 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -71,7 +71,7 @@ impl BenchCmd { | |||
71 | match &self.what { | 71 | match &self.what { |
72 | BenchWhat::Highlight { .. } => { | 72 | BenchWhat::Highlight { .. } => { |
73 | let res = do_work(&mut host, file_id, |analysis| { | 73 | let res = do_work(&mut host, file_id, |analysis| { |
74 | analysis.diagnostics(file_id, true).unwrap(); | 74 | analysis.diagnostics(file_id, true, None).unwrap(); |
75 | analysis.highlight_as_html(file_id, false).unwrap() | 75 | analysis.highlight_as_html(file_id, false).unwrap() |
76 | }); | 76 | }); |
77 | if verbosity.is_verbose() { | 77 | if verbosity.is_verbose() { |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 3371c4fd3..31eb7ff3f 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs | |||
@@ -47,7 +47,7 @@ pub fn diagnostics( | |||
47 | String::from("unknown") | 47 | String::from("unknown") |
48 | }; | 48 | }; |
49 | println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id)); | 49 | println!("processing crate: {}, module: {}", crate_name, _vfs.file_path(file_id)); |
50 | for diagnostic in analysis.diagnostics(file_id, true).unwrap() { | 50 | for diagnostic in analysis.diagnostics(file_id, true, None).unwrap() { |
51 | if matches!(diagnostic.severity, Severity::Error) { | 51 | if matches!(diagnostic.severity, Severity::Error) { |
52 | found_error = true; | 52 | found_error = true; |
53 | } | 53 | } |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 33fb5e9c2..44fd7c286 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | //! configure the server itself, feature flags are passed into analysis, and | 7 | //! configure the server itself, feature flags are passed into analysis, and |
8 | //! tweak things like automatic insertion of `()` in completions. | 8 | //! tweak things like automatic insertion of `()` in completions. |
9 | 9 | ||
10 | use std::{ffi::OsString, path::PathBuf}; | 10 | use std::{collections::HashSet, ffi::OsString, path::PathBuf}; |
11 | 11 | ||
12 | use flycheck::FlycheckConfig; | 12 | use flycheck::FlycheckConfig; |
13 | use ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; | 13 | use ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; |
@@ -45,6 +45,14 @@ pub struct Config { | |||
45 | pub with_sysroot: bool, | 45 | pub with_sysroot: bool, |
46 | pub linked_projects: Vec<LinkedProject>, | 46 | pub linked_projects: Vec<LinkedProject>, |
47 | pub root_path: AbsPathBuf, | 47 | pub root_path: AbsPathBuf, |
48 | |||
49 | pub analysis: AnalysisConfig, | ||
50 | } | ||
51 | |||
52 | /// Configuration parameters for the analysis run. | ||
53 | #[derive(Debug, Default, Clone)] | ||
54 | pub struct AnalysisConfig { | ||
55 | pub disabled_diagnostics: HashSet<String>, | ||
48 | } | 56 | } |
49 | 57 | ||
50 | #[derive(Debug, Clone, Eq, PartialEq)] | 58 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -176,6 +184,8 @@ impl Config { | |||
176 | hover: HoverConfig::default(), | 184 | hover: HoverConfig::default(), |
177 | linked_projects: Vec::new(), | 185 | linked_projects: Vec::new(), |
178 | root_path, | 186 | root_path, |
187 | |||
188 | analysis: AnalysisConfig::default(), | ||
179 | } | 189 | } |
180 | } | 190 | } |
181 | 191 | ||
@@ -293,6 +303,8 @@ impl Config { | |||
293 | goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef, | 303 | goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef, |
294 | }; | 304 | }; |
295 | 305 | ||
306 | self.analysis = AnalysisConfig { disabled_diagnostics: data.analysis_disabledDiagnostics }; | ||
307 | |||
296 | log::info!("Config::update() = {:#?}", self); | 308 | log::info!("Config::update() = {:#?}", self); |
297 | } | 309 | } |
298 | 310 | ||
@@ -357,6 +369,14 @@ impl Config { | |||
357 | self.client_caps.status_notification = get_bool("statusNotification"); | 369 | self.client_caps.status_notification = get_bool("statusNotification"); |
358 | } | 370 | } |
359 | } | 371 | } |
372 | |||
373 | pub fn disabled_diagnostics(&self) -> Option<HashSet<String>> { | ||
374 | if self.analysis.disabled_diagnostics.is_empty() { | ||
375 | None | ||
376 | } else { | ||
377 | Some(self.analysis.disabled_diagnostics.clone()) | ||
378 | } | ||
379 | } | ||
360 | } | 380 | } |
361 | 381 | ||
362 | #[derive(Deserialize)] | 382 | #[derive(Deserialize)] |
@@ -444,5 +464,7 @@ config_data! { | |||
444 | rustfmt_overrideCommand: Option<Vec<String>> = None, | 464 | rustfmt_overrideCommand: Option<Vec<String>> = None, |
445 | 465 | ||
446 | withSysroot: bool = true, | 466 | withSysroot: bool = true, |
467 | |||
468 | analysis_disabledDiagnostics: HashSet<String> = HashSet::new(), | ||
447 | } | 469 | } |
448 | } | 470 | } |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 096127b0c..4f77b1b4d 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -775,7 +775,11 @@ fn handle_fixes( | |||
775 | None => {} | 775 | None => {} |
776 | }; | 776 | }; |
777 | 777 | ||
778 | let diagnostics = snap.analysis.diagnostics(file_id, snap.config.experimental_diagnostics)?; | 778 | let diagnostics = snap.analysis.diagnostics( |
779 | file_id, | ||
780 | snap.config.experimental_diagnostics, | ||
781 | snap.config.disabled_diagnostics(), | ||
782 | )?; | ||
779 | 783 | ||
780 | for fix in diagnostics | 784 | for fix in diagnostics |
781 | .into_iter() | 785 | .into_iter() |
@@ -1049,7 +1053,11 @@ pub(crate) fn publish_diagnostics( | |||
1049 | let line_index = snap.analysis.file_line_index(file_id)?; | 1053 | let line_index = snap.analysis.file_line_index(file_id)?; |
1050 | let diagnostics: Vec<Diagnostic> = snap | 1054 | let diagnostics: Vec<Diagnostic> = snap |
1051 | .analysis | 1055 | .analysis |
1052 | .diagnostics(file_id, snap.config.experimental_diagnostics)? | 1056 | .diagnostics( |
1057 | file_id, | ||
1058 | snap.config.experimental_diagnostics, | ||
1059 | snap.config.disabled_diagnostics(), | ||
1060 | )? | ||
1053 | .into_iter() | 1061 | .into_iter() |
1054 | .map(|d| Diagnostic { | 1062 | .map(|d| Diagnostic { |
1055 | range: to_proto::range(&line_index, d.range), | 1063 | range: to_proto::range(&line_index, d.range), |
diff --git a/editors/code/package.json b/editors/code/package.json index ee5f96bf3..429ff5def 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -609,6 +609,15 @@ | |||
609 | }, | 609 | }, |
610 | "description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", | 610 | "description": "List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", |
611 | "default": [] | 611 | "default": [] |
612 | }, | ||
613 | "rust-analyzer.analysis.disabledDiagnostics": { | ||
614 | "type": "array", | ||
615 | "uniqueItems": true, | ||
616 | "items": { | ||
617 | "type": "string" | ||
618 | }, | ||
619 | "description": "List of rust-analyzer diagnostics to disable", | ||
620 | "default": [] | ||
612 | } | 621 | } |
613 | } | 622 | } |
614 | }, | 623 | }, |