aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_def/src/diagnostics.rs3
-rw-r--r--crates/hir_expand/src/diagnostics.rs1
-rw-r--r--crates/hir_ty/src/diagnostics.rs25
-rw-r--r--crates/ide/src/diagnostics.rs82
-rw-r--r--crates/ide/src/lib.rs10
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs2
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs24
-rw-r--r--crates/rust-analyzer/src/handlers.rs12
-rw-r--r--editors/code/package.json9
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
17impl Diagnostic for UnresolvedModule { 17impl 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;
21use crate::InFile; 21use crate::InFile;
22 22
23pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { 23pub 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
34impl Diagnostic for NoSuchField { 34impl 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
56impl Diagnostic for MissingFields { 60impl 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
89impl Diagnostic for MissingPatFields { 96impl 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
119impl Diagnostic for MissingMatchArms { 129impl 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
137impl Diagnostic for MissingOkInTailExpr { 150impl 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
155impl Diagnostic for BreakOutsideOfLoop { 171impl 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
173impl Diagnostic for MissingUnsafe { 192impl 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
193impl Diagnostic for MismatchedArgCount { 215impl 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
7use std::cell::RefCell; 7use std::{cell::RefCell, collections::HashSet};
8 8
9use base_db::SourceDatabase; 9use base_db::SourceDatabase;
10use hir::{diagnostics::DiagnosticSinkBuilder, Semantics}; 10use 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
85fn diagnostic_with_fix<D: DiagnosticWithFix>(d: &D, sema: &Semantics<RootDatabase>) -> Diagnostic { 96fn 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)]
175mod tests { 189mod 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;
44mod syntax_tree; 44mod syntax_tree;
45mod typing; 45mod typing;
46 46
47use std::sync::Arc; 47use std::{collections::HashSet, sync::Arc};
48 48
49use base_db::{ 49use 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)]
103pub struct Diagnostic { 103pub 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
149impl AnalysisHost { 150impl 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
10use std::{ffi::OsString, path::PathBuf}; 10use std::{collections::HashSet, ffi::OsString, path::PathBuf};
11 11
12use flycheck::FlycheckConfig; 12use flycheck::FlycheckConfig;
13use ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; 13use 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)]
54pub 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 },