aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide_api')
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs5
-rw-r--r--crates/ra_ide_api/src/db.rs9
-rw-r--r--crates/ra_ide_api/src/feature_flags.rs67
-rw-r--r--crates/ra_ide_api/src/lib.rs16
4 files changed, 90 insertions, 7 deletions
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 6878008d3..2b3f98482 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -118,7 +118,10 @@ impl Completions {
118 .set_documentation(func.docs(ctx.db)) 118 .set_documentation(func.docs(ctx.db))
119 .detail(detail); 119 .detail(detail);
120 // If not an import, add parenthesis automatically. 120 // If not an import, add parenthesis automatically.
121 if ctx.use_item_syntax.is_none() && !ctx.is_call { 121 if ctx.use_item_syntax.is_none()
122 && !ctx.is_call
123 && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis")
124 {
122 tested_by!(inserts_parens_for_function_calls); 125 tested_by!(inserts_parens_for_function_calls);
123 let snippet = 126 let snippet =
124 if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 { 127 if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 {
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index fc8252e4b..f2e6b8f12 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -7,7 +7,7 @@ use ra_db::{
7 7
8use crate::{ 8use crate::{
9 symbol_index::{self, SymbolsDatabase}, 9 symbol_index::{self, SymbolsDatabase},
10 LineIndex, 10 FeatureFlags, LineIndex,
11}; 11};
12 12
13#[salsa::database( 13#[salsa::database(
@@ -22,6 +22,7 @@ use crate::{
22#[derive(Debug)] 22#[derive(Debug)]
23pub(crate) struct RootDatabase { 23pub(crate) struct RootDatabase {
24 runtime: salsa::Runtime<RootDatabase>, 24 runtime: salsa::Runtime<RootDatabase>,
25 pub(crate) feature_flags: Arc<FeatureFlags>,
25 pub(crate) last_gc: time::Instant, 26 pub(crate) last_gc: time::Instant,
26 pub(crate) last_gc_check: time::Instant, 27 pub(crate) last_gc_check: time::Instant,
27} 28}
@@ -46,16 +47,17 @@ impl salsa::Database for RootDatabase {
46 47
47impl Default for RootDatabase { 48impl Default for RootDatabase {
48 fn default() -> RootDatabase { 49 fn default() -> RootDatabase {
49 RootDatabase::new(None) 50 RootDatabase::new(None, FeatureFlags::default())
50 } 51 }
51} 52}
52 53
53impl RootDatabase { 54impl RootDatabase {
54 pub fn new(lru_capacity: Option<usize>) -> RootDatabase { 55 pub fn new(lru_capacity: Option<usize>, feature_flags: FeatureFlags) -> RootDatabase {
55 let mut db = RootDatabase { 56 let mut db = RootDatabase {
56 runtime: salsa::Runtime::default(), 57 runtime: salsa::Runtime::default(),
57 last_gc: time::Instant::now(), 58 last_gc: time::Instant::now(),
58 last_gc_check: time::Instant::now(), 59 last_gc_check: time::Instant::now(),
60 feature_flags: Arc::new(feature_flags),
59 }; 61 };
60 db.set_crate_graph_with_durability(Default::default(), Durability::HIGH); 62 db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
61 db.set_local_roots_with_durability(Default::default(), Durability::HIGH); 63 db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
@@ -74,6 +76,7 @@ impl salsa::ParallelDatabase for RootDatabase {
74 runtime: self.runtime.snapshot(self), 76 runtime: self.runtime.snapshot(self),
75 last_gc: self.last_gc, 77 last_gc: self.last_gc,
76 last_gc_check: self.last_gc_check, 78 last_gc_check: self.last_gc_check,
79 feature_flags: Arc::clone(&self.feature_flags),
77 }) 80 })
78 } 81 }
79} 82}
diff --git a/crates/ra_ide_api/src/feature_flags.rs b/crates/ra_ide_api/src/feature_flags.rs
new file mode 100644
index 000000000..9f82ac71c
--- /dev/null
+++ b/crates/ra_ide_api/src/feature_flags.rs
@@ -0,0 +1,67 @@
1use rustc_hash::FxHashMap;
2
3/// Feature flags hold fine-grained toggles for all *user-visible* features of
4/// rust-analyzer.
5///
6/// The exists such that users are able to disable any annoying feature (and,
7/// with many users and many features, some features are bound to be annoying
8/// for some users)
9///
10/// Note that we purposefully use run-time checked strings, and not something
11/// checked at compile time, to keep things simple and flexible.
12///
13/// Also note that, at the moment, `FeatureFlags` also store features for
14/// `ra_lsp_server`. This should be benign layering violation.
15#[derive(Debug)]
16pub struct FeatureFlags {
17 flags: FxHashMap<String, bool>,
18}
19
20impl FeatureFlags {
21 fn new(flags: &[(&str, bool)]) -> FeatureFlags {
22 let flags = flags
23 .iter()
24 .map(|&(name, value)| {
25 check_flag_name(name);
26 (name.to_string(), value)
27 })
28 .collect();
29 FeatureFlags { flags }
30 }
31
32 pub fn set(&mut self, flag: &str, value: bool) -> Result<(), ()> {
33 match self.flags.get_mut(flag) {
34 None => Err(()),
35 Some(slot) => {
36 *slot = value;
37 Ok(())
38 }
39 }
40 }
41
42 pub fn get(&self, flag: &str) -> bool {
43 match self.flags.get(flag) {
44 None => panic!("unknown flag: {:?}", flag),
45 Some(value) => *value,
46 }
47 }
48}
49
50impl Default for FeatureFlags {
51 fn default() -> FeatureFlags {
52 FeatureFlags::new(&[
53 ("lsp.diagnostics", true),
54 ("completion.insertion.add-call-parenthesis", true),
55 ("notifications.workspace-loaded", true),
56 ])
57 }
58}
59
60fn check_flag_name(flag: &str) {
61 for c in flag.bytes() {
62 match c {
63 b'a'..=b'z' | b'-' | b'.' => (),
64 _ => panic!("flag name does not match conventions: {:?}", flag),
65 }
66 }
67}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index fa4ae4379..514dcaf96 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -14,6 +14,7 @@ mod db;
14pub mod mock_analysis; 14pub mod mock_analysis;
15mod symbol_index; 15mod symbol_index;
16mod change; 16mod change;
17mod feature_flags;
17 18
18mod status; 19mod status;
19mod completion; 20mod completion;
@@ -63,6 +64,7 @@ pub use crate::{
63 completion::{CompletionItem, CompletionItemKind, InsertTextFormat}, 64 completion::{CompletionItem, CompletionItemKind, InsertTextFormat},
64 diagnostics::Severity, 65 diagnostics::Severity,
65 display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, 66 display::{file_structure, FunctionSignature, NavigationTarget, StructureNode},
67 feature_flags::FeatureFlags,
66 folding_ranges::{Fold, FoldKind}, 68 folding_ranges::{Fold, FoldKind},
67 hover::HoverResult, 69 hover::HoverResult,
68 inlay_hints::{InlayHint, InlayKind}, 70 inlay_hints::{InlayHint, InlayKind},
@@ -247,13 +249,13 @@ pub struct AnalysisHost {
247 249
248impl Default for AnalysisHost { 250impl Default for AnalysisHost {
249 fn default() -> AnalysisHost { 251 fn default() -> AnalysisHost {
250 AnalysisHost::new(None) 252 AnalysisHost::new(None, FeatureFlags::default())
251 } 253 }
252} 254}
253 255
254impl AnalysisHost { 256impl AnalysisHost {
255 pub fn new(lru_capcity: Option<usize>) -> AnalysisHost { 257 pub fn new(lru_capcity: Option<usize>, feature_flags: FeatureFlags) -> AnalysisHost {
256 AnalysisHost { db: db::RootDatabase::new(lru_capcity) } 258 AnalysisHost { db: db::RootDatabase::new(lru_capcity, feature_flags) }
257 } 259 }
258 /// Returns a snapshot of the current state, which you can query for 260 /// Returns a snapshot of the current state, which you can query for
259 /// semantic information. 261 /// semantic information.
@@ -261,6 +263,10 @@ impl AnalysisHost {
261 Analysis { db: self.db.snapshot() } 263 Analysis { db: self.db.snapshot() }
262 } 264 }
263 265
266 pub fn feature_flags(&self) -> &FeatureFlags {
267 &self.db.feature_flags
268 }
269
264 /// Applies changes to the current state of the world. If there are 270 /// Applies changes to the current state of the world. If there are
265 /// outstanding snapshots, they will be canceled. 271 /// outstanding snapshots, they will be canceled.
266 pub fn apply_change(&mut self, change: AnalysisChange) { 272 pub fn apply_change(&mut self, change: AnalysisChange) {
@@ -319,6 +325,10 @@ impl Analysis {
319 (host.analysis(), file_id) 325 (host.analysis(), file_id)
320 } 326 }
321 327
328 pub fn feature_flags(&self) -> &FeatureFlags {
329 &self.db.feature_flags
330 }
331
322 /// Debug info about the current state of the analysis 332 /// Debug info about the current state of the analysis
323 pub fn status(&self) -> Cancelable<String> { 333 pub fn status(&self) -> Cancelable<String> {
324 self.with_db(|db| status::status(&*db)) 334 self.with_db(|db| status::status(&*db))