aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorIgor Aleksanov <[email protected]>2020-08-07 12:25:55 +0100
committerIgor Aleksanov <[email protected]>2020-08-07 12:25:55 +0100
commit90857ff8b08d73945598bac12a841559e86402b1 (patch)
tree8e98c8d7a1b50d55dbbbf788cda94b11eb3e3395 /crates
parentc463d217a1e001abe6a812f309d93527e28a70c6 (diff)
Add an AnalysisConfig structure and use it to configure diagnostics run
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_expand/src/diagnostics.rs17
-rw-r--r--crates/ra_ide/src/diagnostics.rs24
-rw-r--r--crates/ra_ide/src/lib.rs28
-rw-r--r--crates/rust-analyzer/src/config.rs12
-rw-r--r--crates/rust-analyzer/src/global_state.rs2
5 files changed, 57 insertions, 26 deletions
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs
index bf9fb081a..ef1d61144 100644
--- a/crates/ra_hir_expand/src/diagnostics.rs
+++ b/crates/ra_hir_expand/src/diagnostics.rs
@@ -14,7 +14,7 @@
14//! subsystem provides a separate, non-query-based API which can walk all stored 14//! subsystem provides a separate, non-query-based API which can walk all stored
15//! values and transform them into instances of `Diagnostic`. 15//! values and transform them into instances of `Diagnostic`.
16 16
17use std::{any::Any, collections::HashSet, fmt}; 17use std::{any::Any, fmt};
18 18
19use ra_syntax::{SyntaxNode, SyntaxNodePtr}; 19use ra_syntax::{SyntaxNode, SyntaxNodePtr};
20 20
@@ -50,16 +50,10 @@ pub struct DiagnosticSink<'a> {
50 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, 50 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
51 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, 51 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,
52 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>, 52 default_callback: Box<dyn FnMut(&dyn Diagnostic) + 'a>,
53 disabled_diagnostics: HashSet<String>,
54} 53}
55 54
56impl<'a> DiagnosticSink<'a> { 55impl<'a> DiagnosticSink<'a> {
57 pub fn push(&mut self, d: impl Diagnostic) { 56 pub fn push(&mut self, d: impl Diagnostic) {
58 if self.disabled_diagnostics.contains(&d.name()) {
59 // This diagnostic is disabled, ignore it completely.
60 return;
61 }
62
63 let d: &dyn Diagnostic = &d; 57 let d: &dyn Diagnostic = &d;
64 self._push(d); 58 self._push(d);
65 } 59 }
@@ -83,12 +77,11 @@ impl<'a> DiagnosticSink<'a> {
83pub struct DiagnosticSinkBuilder<'a> { 77pub struct DiagnosticSinkBuilder<'a> {
84 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>, 78 callbacks: Vec<Box<dyn FnMut(&dyn Diagnostic) -> Result<(), ()> + 'a>>,
85 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>, 79 filters: Vec<Box<dyn FnMut(&dyn Diagnostic) -> bool + 'a>>,
86 disabled_diagnostics: HashSet<String>,
87} 80}
88 81
89impl<'a> DiagnosticSinkBuilder<'a> { 82impl<'a> DiagnosticSinkBuilder<'a> {
90 pub fn new() -> Self { 83 pub fn new() -> Self {
91 Self { callbacks: Vec::new(), filters: Vec::new(), disabled_diagnostics: HashSet::new() } 84 Self { callbacks: Vec::new(), filters: Vec::new() }
92 } 85 }
93 86
94 pub fn filter<F: FnMut(&dyn Diagnostic) -> bool + 'a>(mut self, cb: F) -> Self { 87 pub fn filter<F: FnMut(&dyn Diagnostic) -> bool + 'a>(mut self, cb: F) -> Self {
@@ -108,17 +101,11 @@ impl<'a> DiagnosticSinkBuilder<'a> {
108 self 101 self
109 } 102 }
110 103
111 pub fn disable_diagnostic(mut self, diagnostic: impl Into<String>) -> Self {
112 self.disabled_diagnostics.insert(diagnostic.into());
113 self
114 }
115
116 pub fn build<F: FnMut(&dyn Diagnostic) + 'a>(self, default_callback: F) -> DiagnosticSink<'a> { 104 pub fn build<F: FnMut(&dyn Diagnostic) + 'a>(self, default_callback: F) -> DiagnosticSink<'a> {
117 DiagnosticSink { 105 DiagnosticSink {
118 callbacks: self.callbacks, 106 callbacks: self.callbacks,
119 filters: self.filters, 107 filters: self.filters,
120 default_callback: Box::new(default_callback), 108 default_callback: Box::new(default_callback),
121 disabled_diagnostics: self.disabled_diagnostics,
122 } 109 }
123 } 110 }
124} 111}
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 73c0b8275..33e4f1743 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -21,7 +21,7 @@ use ra_syntax::{
21}; 21};
22use ra_text_edit::{TextEdit, TextEditBuilder}; 22use ra_text_edit::{TextEdit, TextEditBuilder};
23 23
24use crate::{Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit}; 24use crate::{AnalysisConfig, Diagnostic, FileId, FileSystemEdit, Fix, SourceFileEdit};
25 25
26#[derive(Debug, Copy, Clone)] 26#[derive(Debug, Copy, Clone)]
27pub enum Severity { 27pub enum Severity {
@@ -33,6 +33,7 @@ pub(crate) fn diagnostics(
33 db: &RootDatabase, 33 db: &RootDatabase,
34 file_id: FileId, 34 file_id: FileId,
35 enable_experimental: bool, 35 enable_experimental: bool,
36 analysis_config: &AnalysisConfig,
36) -> Vec<Diagnostic> { 37) -> Vec<Diagnostic> {
37 let _p = profile("diagnostics"); 38 let _p = profile("diagnostics");
38 let sema = Semantics::new(db); 39 let sema = Semantics::new(db);
@@ -41,6 +42,7 @@ pub(crate) fn diagnostics(
41 42
42 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily. 43 // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
43 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic { 44 res.extend(parse.errors().iter().take(128).map(|err| Diagnostic {
45 name: None,
44 range: err.range(), 46 range: err.range(),
45 message: format!("Syntax Error: {}", err), 47 message: format!("Syntax Error: {}", err),
46 severity: Severity::Error, 48 severity: Severity::Error,
@@ -52,7 +54,7 @@ pub(crate) fn diagnostics(
52 check_struct_shorthand_initialization(&mut res, file_id, &node); 54 check_struct_shorthand_initialization(&mut res, file_id, &node);
53 } 55 }
54 let res = RefCell::new(res); 56 let res = RefCell::new(res);
55 let mut sink = DiagnosticSinkBuilder::new() 57 let mut sink_builder = DiagnosticSinkBuilder::new()
56 .on::<hir::diagnostics::UnresolvedModule, _>(|d| { 58 .on::<hir::diagnostics::UnresolvedModule, _>(|d| {
57 let original_file = d.source().file_id.original_file(db); 59 let original_file = d.source().file_id.original_file(db);
58 let fix = Fix::new( 60 let fix = Fix::new(
@@ -61,6 +63,7 @@ pub(crate) fn diagnostics(
61 .into(), 63 .into(),
62 ); 64 );
63 res.borrow_mut().push(Diagnostic { 65 res.borrow_mut().push(Diagnostic {
66 name: Some(d.name()),
64 range: sema.diagnostics_range(d).range, 67 range: sema.diagnostics_range(d).range,
65 message: d.message(), 68 message: d.message(),
66 severity: Severity::Error, 69 severity: Severity::Error,
@@ -95,6 +98,7 @@ pub(crate) fn diagnostics(
95 }; 98 };
96 99
97 res.borrow_mut().push(Diagnostic { 100 res.borrow_mut().push(Diagnostic {
101 name: Some(d.name()),
98 range: sema.diagnostics_range(d).range, 102 range: sema.diagnostics_range(d).range,
99 message: d.message(), 103 message: d.message(),
100 severity: Severity::Error, 104 severity: Severity::Error,
@@ -108,6 +112,7 @@ pub(crate) fn diagnostics(
108 let source_change = SourceFileEdit { file_id, edit }.into(); 112 let source_change = SourceFileEdit { file_id, edit }.into();
109 let fix = Fix::new("Wrap with ok", source_change); 113 let fix = Fix::new("Wrap with ok", source_change);
110 res.borrow_mut().push(Diagnostic { 114 res.borrow_mut().push(Diagnostic {
115 name: Some(d.name()),
111 range: sema.diagnostics_range(d).range, 116 range: sema.diagnostics_range(d).range,
112 message: d.message(), 117 message: d.message(),
113 severity: Severity::Error, 118 severity: Severity::Error,
@@ -116,6 +121,7 @@ pub(crate) fn diagnostics(
116 }) 121 })
117 .on::<hir::diagnostics::NoSuchField, _>(|d| { 122 .on::<hir::diagnostics::NoSuchField, _>(|d| {
118 res.borrow_mut().push(Diagnostic { 123 res.borrow_mut().push(Diagnostic {
124 name: Some(d.name()),
119 range: sema.diagnostics_range(d).range, 125 range: sema.diagnostics_range(d).range,
120 message: d.message(), 126 message: d.message(),
121 severity: Severity::Error, 127 severity: Severity::Error,
@@ -123,10 +129,20 @@ pub(crate) fn diagnostics(
123 }) 129 })
124 }) 130 })
125 // Only collect experimental diagnostics when they're enabled. 131 // Only collect experimental diagnostics when they're enabled.
126 .filter(|diag| !diag.is_experimental() || enable_experimental) 132 .filter(|diag| !diag.is_experimental() || enable_experimental);
133
134 if !analysis_config.disabled_diagnostics.is_empty() {
135 // Do not collect disabled diagnostics.
136 sink_builder = sink_builder
137 .filter(|diag| !analysis_config.disabled_diagnostics.contains(&diag.name()));
138 }
139
140 // Finalize the `DiagnosticSink` building process.
141 let mut sink = sink_builder
127 // Diagnostics not handled above get no fix and default treatment. 142 // Diagnostics not handled above get no fix and default treatment.
128 .build(|d| { 143 .build(|d| {
129 res.borrow_mut().push(Diagnostic { 144 res.borrow_mut().push(Diagnostic {
145 name: Some(d.name()),
130 message: d.message(), 146 message: d.message(),
131 range: sema.diagnostics_range(d).range, 147 range: sema.diagnostics_range(d).range,
132 severity: Severity::Error, 148 severity: Severity::Error,
@@ -234,6 +250,7 @@ fn check_unnecessary_braces_in_use_statement(
234 }); 250 });
235 251
236 acc.push(Diagnostic { 252 acc.push(Diagnostic {
253 name: None,
237 range, 254 range,
238 message: "Unnecessary braces in use statement".to_string(), 255 message: "Unnecessary braces in use statement".to_string(),
239 severity: Severity::WeakWarning, 256 severity: Severity::WeakWarning,
@@ -279,6 +296,7 @@ fn check_struct_shorthand_initialization(
279 let edit = edit_builder.finish(); 296 let edit = edit_builder.finish();
280 297
281 acc.push(Diagnostic { 298 acc.push(Diagnostic {
299 name: None,
282 range: record_field.syntax().text_range(), 300 range: record_field.syntax().text_range(),
283 message: "Shorthand struct initialization".to_string(), 301 message: "Shorthand struct initialization".to_string(),
284 severity: Severity::WeakWarning, 302 severity: Severity::WeakWarning,
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 0fede0d87..3822b9409 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -45,7 +45,7 @@ mod syntax_highlighting;
45mod syntax_tree; 45mod syntax_tree;
46mod typing; 46mod typing;
47 47
48use std::sync::Arc; 48use std::{collections::HashSet, sync::Arc};
49 49
50use ra_cfg::CfgOptions; 50use ra_cfg::CfgOptions;
51use ra_db::{ 51use ra_db::{
@@ -100,8 +100,15 @@ pub use ra_text_edit::{Indel, TextEdit};
100 100
101pub type Cancelable<T> = Result<T, Canceled>; 101pub type Cancelable<T> = Result<T, Canceled>;
102 102
103/// Configuration parameters for the analysis run.
104#[derive(Debug, Default, Clone)]
105pub struct AnalysisConfig {
106 pub disabled_diagnostics: HashSet<String>,
107}
108
103#[derive(Debug)] 109#[derive(Debug)]
104pub struct Diagnostic { 110pub struct Diagnostic {
111 pub name: Option<String>,
105 pub message: String, 112 pub message: String,
106 pub range: TextRange, 113 pub range: TextRange,
107 pub severity: Severity, 114 pub severity: Severity,
@@ -139,11 +146,16 @@ impl<T> RangeInfo<T> {
139#[derive(Debug)] 146#[derive(Debug)]
140pub struct AnalysisHost { 147pub struct AnalysisHost {
141 db: RootDatabase, 148 db: RootDatabase,
149 config: AnalysisConfig,
142} 150}
143 151
144impl AnalysisHost { 152impl AnalysisHost {
145 pub fn new(lru_capacity: Option<usize>) -> AnalysisHost { 153 pub fn new(lru_capacity: Option<usize>) -> Self {
146 AnalysisHost { db: RootDatabase::new(lru_capacity) } 154 Self::with_config(lru_capacity, AnalysisConfig::default())
155 }
156
157 pub fn with_config(lru_capacity: Option<usize>, config: AnalysisConfig) -> Self {
158 AnalysisHost { db: RootDatabase::new(lru_capacity), config }
147 } 159 }
148 160
149 pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) { 161 pub fn update_lru_capacity(&mut self, lru_capacity: Option<usize>) {
@@ -153,7 +165,7 @@ impl AnalysisHost {
153 /// Returns a snapshot of the current state, which you can query for 165 /// Returns a snapshot of the current state, which you can query for
154 /// semantic information. 166 /// semantic information.
155 pub fn analysis(&self) -> Analysis { 167 pub fn analysis(&self) -> Analysis {
156 Analysis { db: self.db.snapshot() } 168 Analysis { db: self.db.snapshot(), config: self.config.clone() }
157 } 169 }
158 170
159 /// Applies changes to the current state of the world. If there are 171 /// Applies changes to the current state of the world. If there are
@@ -197,6 +209,7 @@ impl Default for AnalysisHost {
197#[derive(Debug)] 209#[derive(Debug)]
198pub struct Analysis { 210pub struct Analysis {
199 db: salsa::Snapshot<RootDatabase>, 211 db: salsa::Snapshot<RootDatabase>,
212 config: AnalysisConfig,
200} 213}
201 214
202// As a general design guideline, `Analysis` API are intended to be independent 215// As a general design guideline, `Analysis` API are intended to be independent
@@ -492,7 +505,7 @@ impl Analysis {
492 file_id: FileId, 505 file_id: FileId,
493 enable_experimental: bool, 506 enable_experimental: bool,
494 ) -> Cancelable<Vec<Diagnostic>> { 507 ) -> Cancelable<Vec<Diagnostic>> {
495 self.with_db(|db| diagnostics::diagnostics(db, file_id, enable_experimental)) 508 self.with_db(|db| diagnostics::diagnostics(db, file_id, enable_experimental, &self.config))
496 } 509 }
497 510
498 /// Returns the edit required to rename reference at the position to the new 511 /// Returns the edit required to rename reference at the position to the new
@@ -518,6 +531,11 @@ impl Analysis {
518 }) 531 })
519 } 532 }
520 533
534 /// Sets the provided config.
535 pub fn set_config(&mut self, config: AnalysisConfig) {
536 self.config = config;
537 }
538
521 /// Performs an operation on that may be Canceled. 539 /// Performs an operation on that may be Canceled.
522 fn with_db<F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, T>( 540 fn with_db<F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, T>(
523 &self, 541 &self,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 70b4512d0..2c1db9546 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -7,11 +7,11 @@
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 lsp_types::ClientCapabilities; 13use lsp_types::ClientCapabilities;
14use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig}; 14use ra_ide::{AnalysisConfig, AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig};
15use ra_project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; 15use ra_project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
16use serde::Deserialize; 16use serde::Deserialize;
17use vfs::AbsPathBuf; 17use vfs::AbsPathBuf;
@@ -45,6 +45,8 @@ 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,
48} 50}
49 51
50#[derive(Debug, Clone, Eq, PartialEq)] 52#[derive(Debug, Clone, Eq, PartialEq)]
@@ -176,6 +178,8 @@ impl Config {
176 hover: HoverConfig::default(), 178 hover: HoverConfig::default(),
177 linked_projects: Vec::new(), 179 linked_projects: Vec::new(),
178 root_path, 180 root_path,
181
182 analysis: AnalysisConfig::default(),
179 } 183 }
180 } 184 }
181 185
@@ -293,6 +297,8 @@ impl Config {
293 goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef, 297 goto_type_def: data.hoverActions_enable && data.hoverActions_gotoTypeDef,
294 }; 298 };
295 299
300 self.analysis = AnalysisConfig { disabled_diagnostics: data.analysis_disabledDiagnostics };
301
296 log::info!("Config::update() = {:#?}", self); 302 log::info!("Config::update() = {:#?}", self);
297 } 303 }
298 304
@@ -444,5 +450,7 @@ config_data! {
444 rustfmt_overrideCommand: Option<Vec<String>> = None, 450 rustfmt_overrideCommand: Option<Vec<String>> = None,
445 451
446 withSysroot: bool = true, 452 withSysroot: bool = true,
453
454 analysis_disabledDiagnostics: HashSet<String> = HashSet::new(),
447 } 455 }
448} 456}
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs
index 0e592ac1b..46cb7ebe2 100644
--- a/crates/rust-analyzer/src/global_state.rs
+++ b/crates/rust-analyzer/src/global_state.rs
@@ -108,7 +108,7 @@ impl GlobalState {
108 Handle { handle, receiver } 108 Handle { handle, receiver }
109 }; 109 };
110 110
111 let analysis_host = AnalysisHost::new(config.lru_capacity); 111 let analysis_host = AnalysisHost::with_config(config.lru_capacity, config.analysis.clone());
112 let (flycheck_sender, flycheck_receiver) = unbounded(); 112 let (flycheck_sender, flycheck_receiver) = unbounded();
113 GlobalState { 113 GlobalState {
114 sender, 114 sender,