diff options
-rw-r--r-- | crates/ra_hir/src/diagnostics.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/diagnostics.rs | 60 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics.rs | 7 | ||||
-rw-r--r-- | crates/ra_ide/src/diagnostics.rs | 156 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 8 | ||||
-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 | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 4 | ||||
-rw-r--r-- | editors/code/package.json | 15 |
10 files changed, 159 insertions, 103 deletions
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs index 11a0ecb8b..266b513dc 100644 --- a/crates/ra_hir/src/diagnostics.rs +++ b/crates/ra_hir/src/diagnostics.rs | |||
@@ -1,6 +1,8 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | pub use hir_def::diagnostics::UnresolvedModule; | 2 | pub use hir_def::diagnostics::UnresolvedModule; |
3 | pub use hir_expand::diagnostics::{AstDiagnostic, Diagnostic, DiagnosticSink}; | 3 | pub use hir_expand::diagnostics::{ |
4 | AstDiagnostic, Diagnostic, DiagnosticSink, DiagnosticSinkBuilder, | ||
5 | }; | ||
4 | pub use hir_ty::diagnostics::{ | 6 | pub use hir_ty::diagnostics::{ |
5 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, | 7 | MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkInTailExpr, NoSuchField, |
6 | }; | 8 | }; |
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs index 545cff9bd..84ba97b14 100644 --- a/crates/ra_hir_expand/src/diagnostics.rs +++ b/crates/ra_hir_expand/src/diagnostics.rs | |||
@@ -24,6 +24,9 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | |||
24 | fn message(&self) -> String; | 24 | fn message(&self) -> String; |
25 | fn source(&self) -> InFile<SyntaxNodePtr>; | 25 | fn source(&self) -> InFile<SyntaxNodePtr>; |
26 | fn as_any(&self) -> &(dyn Any + Send + 'static); | 26 | fn as_any(&self) -> &(dyn Any + Send + 'static); |
27 | fn is_experimental(&self) -> bool { | ||
28 | false | ||
29 | } | ||
27 | } | 30 | } |
28 | 31 | ||
29 | pub trait AstDiagnostic { | 32 | pub trait AstDiagnostic { |
@@ -44,16 +47,48 @@ impl dyn Diagnostic { | |||
44 | 47 | ||
45 | pub struct DiagnosticSink<'a> { | 48 | pub struct DiagnosticSink<'a> { |
46 | callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, | 49 | callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, |
50 | filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, | ||
47 | default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>, | 51 | default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>, |
48 | } | 52 | } |
49 | 53 | ||
50 | impl<'a> DiagnosticSink<'a> { | 54 | impl<'a> DiagnosticSink<'a> { |
51 | /// FIXME: split `new` and `on` into a separate builder type | 55 | pub fn push(&mut self, d: impl Diagnostic) { |
52 | pub fn new(cb: impl FnMut(&dyn Diagnostic) + 'a) -> DiagnosticSink<'a> { | 56 | let d: &dyn Diagnostic = &d; |
53 | DiagnosticSink { callbacks: Vec::new(), default_callback: Box::new(cb) } | 57 | self._push(d); |
58 | } | ||
59 | |||
60 | fn _push(&mut self, d: &dyn Diagnostic) { | ||
61 | for filter in &mut self.filters { | ||
62 | if !filter(d) { | ||
63 | return; | ||
64 | } | ||
65 | } | ||
66 | for cb in &mut self.callbacks { | ||
67 | match cb(d) { | ||
68 | Ok(()) => return, | ||
69 | Err(()) => (), | ||
70 | } | ||
71 | } | ||
72 | (self.default_callback)(d) | ||
54 | } | 73 | } |
74 | } | ||
55 | 75 | ||
56 | pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> DiagnosticSink<'a> { | 76 | pub struct DiagnosticSinkBuilder<'a> { |
77 | callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, | ||
78 | filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, | ||
79 | } | ||
80 | |||
81 | impl<'a> DiagnosticSinkBuilder<'a> { | ||
82 | pub fn new() -> Self { | ||
83 | Self { callbacks: Vec::new(), filters: Vec::new() } | ||
84 | } | ||
85 | |||
86 | pub fn filter<F: FnMut(&dyn Diagnostic) -> bool + 'a>(mut self, cb: F) -> Self { | ||
87 | self.filters.push(Box::new(cb)); | ||
88 | self | ||
89 | } | ||
90 | |||
91 | pub fn on<D: Diagnostic, F: FnMut(&D) + 'a>(mut self, mut cb: F) -> Self { | ||
57 | let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() { | 92 | let cb = move |diag: &dyn Diagnostic| match diag.downcast_ref::<D>() { |
58 | Some(d) => { | 93 | Some(d) => { |
59 | cb(d); | 94 | cb(d); |
@@ -65,18 +100,11 @@ impl<'a> DiagnosticSink<'a> { | |||
65 | self | 100 | self |
66 | } | 101 | } |
67 | 102 | ||
68 | pub fn push(&mut self, d: impl Diagnostic) { | 103 | pub fn build<F: FnMut(&dyn Diagnostic) + 'a>(self, default_callback: F) -> DiagnosticSink<'a> { |
69 | let d: &dyn Diagnostic = &d; | 104 | DiagnosticSink { |
70 | self._push(d); | 105 | callbacks: self.callbacks, |
71 | } | 106 | filters: self.filters, |
72 | 107 | default_callback: Box::new(default_callback), | |
73 | fn _push(&mut self, d: &dyn Diagnostic) { | ||
74 | for cb in self.callbacks.iter_mut() { | ||
75 | match cb(d) { | ||
76 | Ok(()) => return, | ||
77 | Err(()) => (), | ||
78 | } | ||
79 | } | 108 | } |
80 | (self.default_callback)(d) | ||
81 | } | 109 | } |
82 | } | 110 | } |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index d3ee9cf55..885abbaf2 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -234,6 +234,9 @@ impl Diagnostic for MismatchedArgCount { | |||
234 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | 234 | fn as_any(&self) -> &(dyn Any + Send + 'static) { |
235 | self | 235 | self |
236 | } | 236 | } |
237 | fn is_experimental(&self) -> bool { | ||
238 | true | ||
239 | } | ||
237 | } | 240 | } |
238 | 241 | ||
239 | impl AstDiagnostic for MismatchedArgCount { | 242 | impl AstDiagnostic for MismatchedArgCount { |
@@ -248,7 +251,7 @@ impl AstDiagnostic for MismatchedArgCount { | |||
248 | #[cfg(test)] | 251 | #[cfg(test)] |
249 | mod tests { | 252 | mod tests { |
250 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; | 253 | use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId}; |
251 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSink}; | 254 | use hir_expand::diagnostics::{Diagnostic, DiagnosticSinkBuilder}; |
252 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; | 255 | use ra_db::{fixture::WithFixture, FileId, SourceDatabase, SourceDatabaseExt}; |
253 | use ra_syntax::{TextRange, TextSize}; | 256 | use ra_syntax::{TextRange, TextSize}; |
254 | use rustc_hash::FxHashMap; | 257 | use rustc_hash::FxHashMap; |
@@ -280,7 +283,7 @@ mod tests { | |||
280 | } | 283 | } |
281 | 284 | ||
282 | for f in fns { | 285 | for f in fns { |
283 | let mut sink = DiagnosticSink::new(&mut cb); | 286 | let mut sink = DiagnosticSinkBuilder::new().build(&mut cb); |
284 | validate_body(self, f.into(), &mut sink); | 287 | validate_body(self, f.into(), &mut sink); |
285 | } | 288 | } |
286 | } | 289 | } |
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index e029af0dc..897177d05 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs | |||
@@ -7,7 +7,7 @@ | |||
7 | use std::cell::RefCell; | 7 | use std::cell::RefCell; |
8 | 8 | ||
9 | use hir::{ | 9 | use hir::{ |
10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink}, | 10 | diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSinkBuilder}, |
11 | HasSource, HirDisplay, Semantics, VariantDef, | 11 | HasSource, HirDisplay, Semantics, VariantDef, |
12 | }; | 12 | }; |
13 | use itertools::Itertools; | 13 | use itertools::Itertools; |
@@ -29,7 +29,11 @@ pub enum Severity { | |||
29 | WeakWarning, | 29 | WeakWarning, |
30 | } | 30 | } |
31 | 31 | ||
32 | pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> { | 32 | pub(crate) fn diagnostics( |
33 | db: &RootDatabase, | ||
34 | file_id: FileId, | ||
35 | enable_experimental: bool, | ||
36 | ) -> Vec<Diagnostic> { | ||
33 | let _p = profile("diagnostics"); | 37 | let _p = profile("diagnostics"); |
34 | let sema = Semantics::new(db); | 38 | let sema = Semantics::new(db); |
35 | let parse = db.parse(file_id); | 39 | let parse = db.parse(file_id); |
@@ -48,79 +52,85 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic> | |||
48 | check_struct_shorthand_initialization(&mut res, file_id, &node); | 52 | check_struct_shorthand_initialization(&mut res, file_id, &node); |
49 | } | 53 | } |
50 | let res = RefCell::new(res); | 54 | let res = RefCell::new(res); |
51 | let mut sink = DiagnosticSink::new(|d| { | 55 | let mut sink = DiagnosticSinkBuilder::new() |
52 | res.borrow_mut().push(Diagnostic { | 56 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { |
53 | message: d.message(), | 57 | let original_file = d.source().file_id.original_file(db); |
54 | range: sema.diagnostics_range(d).range, | 58 | let fix = Fix::new( |
55 | severity: Severity::Error, | 59 | "Create module", |
56 | fix: None, | 60 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() } |
57 | }) | 61 | .into(), |
58 | }) | 62 | ); |
59 | .on::<hir::diagnostics::UnresolvedModule, _>(|d| { | 63 | res.borrow_mut().push(Diagnostic { |
60 | let original_file = d.source().file_id.original_file(db); | 64 | range: sema.diagnostics_range(d).range, |
61 | let fix = Fix::new( | 65 | message: d.message(), |
62 | "Create module", | 66 | severity: Severity::Error, |
63 | FileSystemEdit::CreateFile { anchor: original_file, dst: d.candidate.clone() }.into(), | 67 | fix: Some(fix), |
64 | ); | 68 | }) |
65 | res.borrow_mut().push(Diagnostic { | ||
66 | range: sema.diagnostics_range(d).range, | ||
67 | message: d.message(), | ||
68 | severity: Severity::Error, | ||
69 | fix: Some(fix), | ||
70 | }) | 69 | }) |
71 | }) | 70 | .on::<hir::diagnostics::MissingFields, _>(|d| { |
72 | .on::<hir::diagnostics::MissingFields, _>(|d| { | 71 | // Note that although we could add a diagnostics to |
73 | // Note that although we could add a diagnostics to | 72 | // fill the missing tuple field, e.g : |
74 | // fill the missing tuple field, e.g : | 73 | // `struct A(usize);` |
75 | // `struct A(usize);` | 74 | // `let a = A { 0: () }` |
76 | // `let a = A { 0: () }` | 75 | // but it is uncommon usage and it should not be encouraged. |
77 | // but it is uncommon usage and it should not be encouraged. | 76 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { |
78 | let fix = if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) { | 77 | None |
79 | None | 78 | } else { |
80 | } else { | 79 | let mut field_list = d.ast(db); |
81 | let mut field_list = d.ast(db); | 80 | for f in d.missed_fields.iter() { |
82 | for f in d.missed_fields.iter() { | 81 | let field = |
83 | let field = | 82 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); |
84 | make::record_field(make::name_ref(&f.to_string()), Some(make::expr_unit())); | 83 | field_list = field_list.append_field(&field); |
85 | field_list = field_list.append_field(&field); | 84 | } |
86 | } | 85 | |
87 | 86 | let edit = { | |
88 | let edit = { | 87 | let mut builder = TextEditBuilder::default(); |
89 | let mut builder = TextEditBuilder::default(); | 88 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()) |
90 | algo::diff(&d.ast(db).syntax(), &field_list.syntax()).into_text_edit(&mut builder); | 89 | .into_text_edit(&mut builder); |
91 | builder.finish() | 90 | builder.finish() |
91 | }; | ||
92 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
92 | }; | 93 | }; |
93 | Some(Fix::new("Fill struct fields", SourceFileEdit { file_id, edit }.into())) | ||
94 | }; | ||
95 | 94 | ||
96 | res.borrow_mut().push(Diagnostic { | 95 | res.borrow_mut().push(Diagnostic { |
97 | range: sema.diagnostics_range(d).range, | 96 | range: sema.diagnostics_range(d).range, |
98 | message: d.message(), | 97 | message: d.message(), |
99 | severity: Severity::Error, | 98 | severity: Severity::Error, |
100 | fix, | 99 | fix, |
100 | }) | ||
101 | }) | 101 | }) |
102 | }) | 102 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { |
103 | .on::<hir::diagnostics::MissingOkInTailExpr, _>(|d| { | 103 | let node = d.ast(db); |
104 | let node = d.ast(db); | 104 | let replacement = format!("Ok({})", node.syntax()); |
105 | let replacement = format!("Ok({})", node.syntax()); | 105 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); |
106 | let edit = TextEdit::replace(node.syntax().text_range(), replacement); | 106 | let source_change = SourceFileEdit { file_id, edit }.into(); |
107 | let source_change = SourceFileEdit { file_id, edit }.into(); | 107 | let fix = Fix::new("Wrap with ok", source_change); |
108 | let fix = Fix::new("Wrap with ok", source_change); | 108 | res.borrow_mut().push(Diagnostic { |
109 | res.borrow_mut().push(Diagnostic { | 109 | range: sema.diagnostics_range(d).range, |
110 | range: sema.diagnostics_range(d).range, | 110 | message: d.message(), |
111 | message: d.message(), | 111 | severity: Severity::Error, |
112 | severity: Severity::Error, | 112 | fix: Some(fix), |
113 | fix: Some(fix), | 113 | }) |
114 | }) | 114 | }) |
115 | }) | 115 | .on::<hir::diagnostics::NoSuchField, _>(|d| { |
116 | .on::<hir::diagnostics::NoSuchField, _>(|d| { | 116 | res.borrow_mut().push(Diagnostic { |
117 | res.borrow_mut().push(Diagnostic { | 117 | range: sema.diagnostics_range(d).range, |
118 | range: sema.diagnostics_range(d).range, | 118 | message: d.message(), |
119 | message: d.message(), | 119 | severity: Severity::Error, |
120 | severity: Severity::Error, | 120 | fix: missing_struct_field_fix(&sema, file_id, d), |
121 | fix: missing_struct_field_fix(&sema, file_id, d), | 121 | }) |
122 | }) | 122 | }) |
123 | }); | 123 | // Only collect experimental diagnostics when they're enabled. |
124 | .filter(|diag| !diag.is_experimental() || enable_experimental) | ||
125 | // Diagnostics not handled above get no fix and default treatment. | ||
126 | .build(|d| { | ||
127 | res.borrow_mut().push(Diagnostic { | ||
128 | message: d.message(), | ||
129 | range: sema.diagnostics_range(d).range, | ||
130 | severity: Severity::Error, | ||
131 | fix: None, | ||
132 | }) | ||
133 | }); | ||
124 | 134 | ||
125 | if let Some(m) = sema.to_module_def(file_id) { | 135 | if let Some(m) = sema.to_module_def(file_id) { |
126 | m.diagnostics(db, &mut sink); | 136 | m.diagnostics(db, &mut sink); |
@@ -298,7 +308,7 @@ mod tests { | |||
298 | let after = trim_indent(ra_fixture_after); | 308 | let after = trim_indent(ra_fixture_after); |
299 | 309 | ||
300 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); | 310 | let (analysis, file_position) = analysis_and_position(ra_fixture_before); |
301 | let diagnostic = analysis.diagnostics(file_position.file_id).unwrap().pop().unwrap(); | 311 | let diagnostic = analysis.diagnostics(file_position.file_id, true).unwrap().pop().unwrap(); |
302 | let mut fix = diagnostic.fix.unwrap(); | 312 | let mut fix = diagnostic.fix.unwrap(); |
303 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; | 313 | let edit = fix.source_change.source_file_edits.pop().unwrap().edit; |
304 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); | 314 | let target_file_contents = analysis.file_text(file_position.file_id).unwrap(); |
@@ -324,7 +334,7 @@ mod tests { | |||
324 | let ra_fixture_after = &trim_indent(ra_fixture_after); | 334 | let ra_fixture_after = &trim_indent(ra_fixture_after); |
325 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); | 335 | let (analysis, file_pos) = analysis_and_position(ra_fixture_before); |
326 | let current_file_id = file_pos.file_id; | 336 | let current_file_id = file_pos.file_id; |
327 | let diagnostic = analysis.diagnostics(current_file_id).unwrap().pop().unwrap(); | 337 | let diagnostic = analysis.diagnostics(current_file_id, true).unwrap().pop().unwrap(); |
328 | let mut fix = diagnostic.fix.unwrap(); | 338 | let mut fix = diagnostic.fix.unwrap(); |
329 | let edit = fix.source_change.source_file_edits.pop().unwrap(); | 339 | let edit = fix.source_change.source_file_edits.pop().unwrap(); |
330 | let changed_file_id = edit.file_id; | 340 | let changed_file_id = edit.file_id; |
@@ -345,14 +355,14 @@ mod tests { | |||
345 | let analysis = mock.analysis(); | 355 | let analysis = mock.analysis(); |
346 | let diagnostics = files | 356 | let diagnostics = files |
347 | .into_iter() | 357 | .into_iter() |
348 | .flat_map(|file_id| analysis.diagnostics(file_id).unwrap()) | 358 | .flat_map(|file_id| analysis.diagnostics(file_id, true).unwrap()) |
349 | .collect::<Vec<_>>(); | 359 | .collect::<Vec<_>>(); |
350 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); | 360 | assert_eq!(diagnostics.len(), 0, "unexpected diagnostics:\n{:#?}", diagnostics); |
351 | } | 361 | } |
352 | 362 | ||
353 | fn check_expect(ra_fixture: &str, expect: Expect) { | 363 | fn check_expect(ra_fixture: &str, expect: Expect) { |
354 | let (analysis, file_id) = single_file(ra_fixture); | 364 | let (analysis, file_id) = single_file(ra_fixture); |
355 | let diagnostics = analysis.diagnostics(file_id).unwrap(); | 365 | let diagnostics = analysis.diagnostics(file_id, true).unwrap(); |
356 | expect.assert_debug_eq(&diagnostics) | 366 | expect.assert_debug_eq(&diagnostics) |
357 | } | 367 | } |
358 | 368 | ||
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 7356e947b..4c4d9f6fa 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -487,8 +487,12 @@ impl Analysis { | |||
487 | } | 487 | } |
488 | 488 | ||
489 | /// Computes the set of diagnostics for the given file. | 489 | /// Computes the set of diagnostics for the given file. |
490 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 490 | pub fn diagnostics( |
491 | self.with_db(|db| diagnostics::diagnostics(db, file_id)) | 491 | &self, |
492 | file_id: FileId, | ||
493 | enable_experimental: bool, | ||
494 | ) -> Cancelable<Vec<Diagnostic>> { | ||
495 | self.with_db(|db| diagnostics::diagnostics(db, file_id, enable_experimental)) | ||
492 | } | 496 | } |
493 | 497 | ||
494 | /// Returns the edit required to rename reference at the position to the new | 498 | /// 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 9299879b7..076184ad6 100644 --- a/crates/rust-analyzer/src/cli/analysis_bench.rs +++ b/crates/rust-analyzer/src/cli/analysis_bench.rs | |||
@@ -70,7 +70,7 @@ pub fn analysis_bench( | |||
70 | match &what { | 70 | match &what { |
71 | BenchWhat::Highlight { .. } => { | 71 | BenchWhat::Highlight { .. } => { |
72 | let res = do_work(&mut host, file_id, |analysis| { | 72 | let res = do_work(&mut host, file_id, |analysis| { |
73 | analysis.diagnostics(file_id).unwrap(); | 73 | analysis.diagnostics(file_id, true).unwrap(); |
74 | analysis.highlight_as_html(file_id, false).unwrap() | 74 | analysis.highlight_as_html(file_id, false).unwrap() |
75 | }); | 75 | }); |
76 | if verbosity.is_verbose() { | 76 | if verbosity.is_verbose() { |
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 6f3c1c1f9..4ac8c8772 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).unwrap() { | 50 | for diagnostic in analysis.diagnostics(file_id, true).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 8947ccf07..e11c8b909 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -23,6 +23,7 @@ pub struct Config { | |||
23 | pub client_caps: ClientCapsConfig, | 23 | pub client_caps: ClientCapsConfig, |
24 | 24 | ||
25 | pub publish_diagnostics: bool, | 25 | pub publish_diagnostics: bool, |
26 | pub experimental_diagnostics: bool, | ||
26 | pub diagnostics: DiagnosticsConfig, | 27 | pub diagnostics: DiagnosticsConfig, |
27 | pub lru_capacity: Option<usize>, | 28 | pub lru_capacity: Option<usize>, |
28 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, | 29 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, |
@@ -137,6 +138,7 @@ impl Config { | |||
137 | 138 | ||
138 | with_sysroot: true, | 139 | with_sysroot: true, |
139 | publish_diagnostics: true, | 140 | publish_diagnostics: true, |
141 | experimental_diagnostics: true, | ||
140 | diagnostics: DiagnosticsConfig::default(), | 142 | diagnostics: DiagnosticsConfig::default(), |
141 | lru_capacity: None, | 143 | lru_capacity: None, |
142 | proc_macro_srv: None, | 144 | proc_macro_srv: None, |
@@ -187,6 +189,7 @@ impl Config { | |||
187 | 189 | ||
188 | self.with_sysroot = data.withSysroot; | 190 | self.with_sysroot = data.withSysroot; |
189 | self.publish_diagnostics = data.diagnostics_enable; | 191 | self.publish_diagnostics = data.diagnostics_enable; |
192 | self.experimental_diagnostics = data.diagnostics_enableExperimental; | ||
190 | self.diagnostics = DiagnosticsConfig { | 193 | self.diagnostics = DiagnosticsConfig { |
191 | warnings_as_info: data.diagnostics_warningsAsInfo, | 194 | warnings_as_info: data.diagnostics_warningsAsInfo, |
192 | warnings_as_hint: data.diagnostics_warningsAsHint, | 195 | warnings_as_hint: data.diagnostics_warningsAsHint, |
@@ -405,6 +408,7 @@ config_data! { | |||
405 | completion_postfix_enable: bool = true, | 408 | completion_postfix_enable: bool = true, |
406 | 409 | ||
407 | diagnostics_enable: bool = true, | 410 | diagnostics_enable: bool = true, |
411 | diagnostics_enableExperimental: bool = true, | ||
408 | diagnostics_warningsAsHint: Vec<String> = Vec::new(), | 412 | diagnostics_warningsAsHint: Vec<String> = Vec::new(), |
409 | diagnostics_warningsAsInfo: Vec<String> = Vec::new(), | 413 | diagnostics_warningsAsInfo: Vec<String> = Vec::new(), |
410 | 414 | ||
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index cad92c444..cd309ed74 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -774,7 +774,7 @@ fn handle_fixes( | |||
774 | None => {} | 774 | None => {} |
775 | }; | 775 | }; |
776 | 776 | ||
777 | let diagnostics = snap.analysis.diagnostics(file_id)?; | 777 | let diagnostics = snap.analysis.diagnostics(file_id, snap.config.experimental_diagnostics)?; |
778 | 778 | ||
779 | let fixes_from_diagnostics = diagnostics | 779 | let fixes_from_diagnostics = diagnostics |
780 | .into_iter() | 780 | .into_iter() |
@@ -1040,7 +1040,7 @@ pub(crate) fn publish_diagnostics( | |||
1040 | let line_index = snap.analysis.file_line_index(file_id)?; | 1040 | let line_index = snap.analysis.file_line_index(file_id)?; |
1041 | let diagnostics: Vec<Diagnostic> = snap | 1041 | let diagnostics: Vec<Diagnostic> = snap |
1042 | .analysis | 1042 | .analysis |
1043 | .diagnostics(file_id)? | 1043 | .diagnostics(file_id, snap.config.experimental_diagnostics)? |
1044 | .into_iter() | 1044 | .into_iter() |
1045 | .map(|d| Diagnostic { | 1045 | .map(|d| Diagnostic { |
1046 | range: to_proto::range(&line_index, d.range), | 1046 | range: to_proto::range(&line_index, d.range), |
diff --git a/editors/code/package.json b/editors/code/package.json index 448e2269f..658c913fd 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -200,11 +200,6 @@ | |||
200 | "type": "object", | 200 | "type": "object", |
201 | "title": "Rust Analyzer", | 201 | "title": "Rust Analyzer", |
202 | "properties": { | 202 | "properties": { |
203 | "rust-analyzer.diagnostics.enable": { | ||
204 | "type": "boolean", | ||
205 | "default": true, | ||
206 | "markdownDescription": "Whether to show native rust-analyzer diagnostics." | ||
207 | }, | ||
208 | "rust-analyzer.lruCapacity": { | 203 | "rust-analyzer.lruCapacity": { |
209 | "type": [ | 204 | "type": [ |
210 | "null", | 205 | "null", |
@@ -579,6 +574,16 @@ | |||
579 | "type": "boolean", | 574 | "type": "boolean", |
580 | "default": true | 575 | "default": true |
581 | }, | 576 | }, |
577 | "rust-analyzer.diagnostics.enable": { | ||
578 | "type": "boolean", | ||
579 | "default": true, | ||
580 | "markdownDescription": "Whether to show native rust-analyzer diagnostics." | ||
581 | }, | ||
582 | "rust-analyzer.diagnostics.enableExperimental": { | ||
583 | "type": "boolean", | ||
584 | "default": true, | ||
585 | "markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might have more false positives than usual." | ||
586 | }, | ||
582 | "rust-analyzer.diagnostics.warningsAsInfo": { | 587 | "rust-analyzer.diagnostics.warningsAsInfo": { |
583 | "type": "array", | 588 | "type": "array", |
584 | "uniqueItems": true, | 589 | "uniqueItems": true, |