aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-05-17 11:09:53 +0100
committerAleksey Kladov <[email protected]>2020-05-19 19:28:27 +0100
commitc847c079fd66d7ed09c64ff398baf05317b16500 (patch)
treef7560983031a6f122156b3d4c3fccaf3f4c23d5c
parent131849f2abd94dc8143f0c5d65e022136f29561a (diff)
Add AssistConfig
-rw-r--r--crates/ra_assists/src/assist_config.rs27
-rw-r--r--crates/ra_assists/src/assist_context.rs51
-rw-r--r--crates/ra_assists/src/lib.rs15
-rw-r--r--crates/ra_assists/src/tests.rs38
-rw-r--r--crates/ra_ide/src/completion.rs2
-rw-r--r--crates/ra_ide/src/completion/test_utils.rs2
-rw-r--r--crates/ra_ide/src/diagnostics.rs2
-rw-r--r--crates/ra_ide/src/lib.rs10
-rw-r--r--crates/ra_ide/src/references/rename.rs3
-rw-r--r--crates/ra_ide_db/src/source_change.rs5
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs5
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs6
13 files changed, 129 insertions, 39 deletions
diff --git a/crates/ra_assists/src/assist_config.rs b/crates/ra_assists/src/assist_config.rs
new file mode 100644
index 000000000..c0a0226fb
--- /dev/null
+++ b/crates/ra_assists/src/assist_config.rs
@@ -0,0 +1,27 @@
1//! Settings for tweaking assists.
2//!
3//! The fun thing here is `SnippetCap` -- this type can only be created in this
4//! module, and we use to statically check that we only produce snippet
5//! assists if we are allowed to.
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub struct AssistConfig {
9 pub snippet_cap: Option<SnippetCap>,
10}
11
12impl AssistConfig {
13 pub fn allow_snippets(&mut self, yes: bool) {
14 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
15 }
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub struct SnippetCap {
20 _private: (),
21}
22
23impl Default for AssistConfig {
24 fn default() -> Self {
25 AssistConfig { snippet_cap: Some(SnippetCap { _private: () }) }
26 }
27}
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index a680f752b..b90bbf8b2 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -15,7 +15,10 @@ use ra_syntax::{
15}; 15};
16use ra_text_edit::TextEditBuilder; 16use ra_text_edit::TextEditBuilder;
17 17
18use crate::{Assist, AssistId, GroupLabel, ResolvedAssist}; 18use crate::{
19 assist_config::{AssistConfig, SnippetCap},
20 Assist, AssistId, GroupLabel, ResolvedAssist,
21};
19 22
20/// `AssistContext` allows to apply an assist or check if it could be applied. 23/// `AssistContext` allows to apply an assist or check if it could be applied.
21/// 24///
@@ -48,6 +51,7 @@ use crate::{Assist, AssistId, GroupLabel, ResolvedAssist};
48/// moment, because the LSP API is pretty awkward in this place, and it's much 51/// moment, because the LSP API is pretty awkward in this place, and it's much
49/// easier to just compute the edit eagerly :-) 52/// easier to just compute the edit eagerly :-)
50pub(crate) struct AssistContext<'a> { 53pub(crate) struct AssistContext<'a> {
54 pub(crate) config: &'a AssistConfig,
51 pub(crate) sema: Semantics<'a, RootDatabase>, 55 pub(crate) sema: Semantics<'a, RootDatabase>,
52 pub(crate) db: &'a RootDatabase, 56 pub(crate) db: &'a RootDatabase,
53 pub(crate) frange: FileRange, 57 pub(crate) frange: FileRange,
@@ -55,10 +59,14 @@ pub(crate) struct AssistContext<'a> {
55} 59}
56 60
57impl<'a> AssistContext<'a> { 61impl<'a> AssistContext<'a> {
58 pub fn new(sema: Semantics<'a, RootDatabase>, frange: FileRange) -> AssistContext<'a> { 62 pub(crate) fn new(
63 sema: Semantics<'a, RootDatabase>,
64 config: &'a AssistConfig,
65 frange: FileRange,
66 ) -> AssistContext<'a> {
59 let source_file = sema.parse(frange.file_id); 67 let source_file = sema.parse(frange.file_id);
60 let db = sema.db; 68 let db = sema.db;
61 AssistContext { sema, db, frange, source_file } 69 AssistContext { config, sema, db, frange, source_file }
62 } 70 }
63 71
64 // NB, this ignores active selection. 72 // NB, this ignores active selection.
@@ -165,11 +173,17 @@ pub(crate) struct AssistBuilder {
165 edit: TextEditBuilder, 173 edit: TextEditBuilder,
166 cursor_position: Option<TextSize>, 174 cursor_position: Option<TextSize>,
167 file: FileId, 175 file: FileId,
176 is_snippet: bool,
168} 177}
169 178
170impl AssistBuilder { 179impl AssistBuilder {
171 pub(crate) fn new(file: FileId) -> AssistBuilder { 180 pub(crate) fn new(file: FileId) -> AssistBuilder {
172 AssistBuilder { edit: TextEditBuilder::default(), cursor_position: None, file } 181 AssistBuilder {
182 edit: TextEditBuilder::default(),
183 cursor_position: None,
184 file,
185 is_snippet: false,
186 }
173 } 187 }
174 188
175 /// Remove specified `range` of text. 189 /// Remove specified `range` of text.
@@ -180,10 +194,30 @@ impl AssistBuilder {
180 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) { 194 pub(crate) fn insert(&mut self, offset: TextSize, text: impl Into<String>) {
181 self.edit.insert(offset, text.into()) 195 self.edit.insert(offset, text.into())
182 } 196 }
197 /// Append specified `text` at the given `offset`
198 pub(crate) fn insert_snippet(
199 &mut self,
200 _cap: SnippetCap,
201 offset: TextSize,
202 text: impl Into<String>,
203 ) {
204 self.is_snippet = true;
205 self.edit.insert(offset, text.into())
206 }
183 /// Replaces specified `range` of text with a given string. 207 /// Replaces specified `range` of text with a given string.
184 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) { 208 pub(crate) fn replace(&mut self, range: TextRange, replace_with: impl Into<String>) {
185 self.edit.replace(range, replace_with.into()) 209 self.edit.replace(range, replace_with.into())
186 } 210 }
211 /// Append specified `text` at the given `offset`
212 pub(crate) fn replace_snippet(
213 &mut self,
214 _cap: SnippetCap,
215 range: TextRange,
216 replace_with: impl Into<String>,
217 ) {
218 self.is_snippet = true;
219 self.edit.replace(range, replace_with.into())
220 }
187 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) { 221 pub(crate) fn replace_ast<N: AstNode>(&mut self, old: N, new: N) {
188 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit) 222 algo::diff(old.syntax(), new.syntax()).into_text_edit(&mut self.edit)
189 } 223 }
@@ -227,7 +261,12 @@ impl AssistBuilder {
227 if edit.is_empty() && self.cursor_position.is_none() { 261 if edit.is_empty() && self.cursor_position.is_none() {
228 panic!("Only call `add_assist` if the assist can be applied") 262 panic!("Only call `add_assist` if the assist can be applied")
229 } 263 }
230 SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position } 264 let mut res =
231 .into_source_change(self.file) 265 SingleFileChange { label: change_label, edit, cursor_position: self.cursor_position }
266 .into_source_change(self.file);
267 if self.is_snippet {
268 res.is_snippet = true;
269 }
270 res
232 } 271 }
233} 272}
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index b6dc7cb1b..7f0a723c9 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -10,6 +10,7 @@ macro_rules! eprintln {
10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 10 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
11} 11}
12 12
13mod assist_config;
13mod assist_context; 14mod assist_context;
14mod marks; 15mod marks;
15#[cfg(test)] 16#[cfg(test)]
@@ -24,6 +25,8 @@ use ra_syntax::TextRange;
24 25
25pub(crate) use crate::assist_context::{AssistContext, Assists}; 26pub(crate) use crate::assist_context::{AssistContext, Assists};
26 27
28pub use assist_config::AssistConfig;
29
27/// Unique identifier of the assist, should not be shown to the user 30/// Unique identifier of the assist, should not be shown to the user
28/// directly. 31/// directly.
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -54,9 +57,9 @@ impl Assist {
54 /// 57 ///
55 /// Assists are returned in the "unresolved" state, that is only labels are 58 /// Assists are returned in the "unresolved" state, that is only labels are
56 /// returned, without actual edits. 59 /// returned, without actual edits.
57 pub fn unresolved(db: &RootDatabase, range: FileRange) -> Vec<Assist> { 60 pub fn unresolved(db: &RootDatabase, config: &AssistConfig, range: FileRange) -> Vec<Assist> {
58 let sema = Semantics::new(db); 61 let sema = Semantics::new(db);
59 let ctx = AssistContext::new(sema, range); 62 let ctx = AssistContext::new(sema, config, range);
60 let mut acc = Assists::new_unresolved(&ctx); 63 let mut acc = Assists::new_unresolved(&ctx);
61 handlers::all().iter().for_each(|handler| { 64 handlers::all().iter().for_each(|handler| {
62 handler(&mut acc, &ctx); 65 handler(&mut acc, &ctx);
@@ -68,9 +71,13 @@ impl Assist {
68 /// 71 ///
69 /// Assists are returned in the "resolved" state, that is with edit fully 72 /// Assists are returned in the "resolved" state, that is with edit fully
70 /// computed. 73 /// computed.
71 pub fn resolved(db: &RootDatabase, range: FileRange) -> Vec<ResolvedAssist> { 74 pub fn resolved(
75 db: &RootDatabase,
76 config: &AssistConfig,
77 range: FileRange,
78 ) -> Vec<ResolvedAssist> {
72 let sema = Semantics::new(db); 79 let sema = Semantics::new(db);
73 let ctx = AssistContext::new(sema, range); 80 let ctx = AssistContext::new(sema, config, range);
74 let mut acc = Assists::new_resolved(&ctx); 81 let mut acc = Assists::new_resolved(&ctx);
75 handlers::all().iter().for_each(|handler| { 82 handlers::all().iter().for_each(|handler| {
76 handler(&mut acc, &ctx); 83 handler(&mut acc, &ctx);
diff --git a/crates/ra_assists/src/tests.rs b/crates/ra_assists/src/tests.rs
index a3eacb8f1..9ba3da786 100644
--- a/crates/ra_assists/src/tests.rs
+++ b/crates/ra_assists/src/tests.rs
@@ -11,7 +11,7 @@ use test_utils::{
11 RangeOrOffset, 11 RangeOrOffset,
12}; 12};
13 13
14use crate::{handlers::Handler, Assist, AssistContext, Assists}; 14use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, Assists};
15 15
16pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { 16pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
17 let (mut db, file_id) = RootDatabase::with_single_file(text); 17 let (mut db, file_id) = RootDatabase::with_single_file(text);
@@ -41,14 +41,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
41 let (db, file_id) = crate::tests::with_single_file(&before); 41 let (db, file_id) = crate::tests::with_single_file(&before);
42 let frange = FileRange { file_id, range: selection.into() }; 42 let frange = FileRange { file_id, range: selection.into() };
43 43
44 let mut assist = Assist::resolved(&db, frange) 44 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange)
45 .into_iter() 45 .into_iter()
46 .find(|assist| assist.assist.id.0 == assist_id) 46 .find(|assist| assist.assist.id.0 == assist_id)
47 .unwrap_or_else(|| { 47 .unwrap_or_else(|| {
48 panic!( 48 panic!(
49 "\n\nAssist is not applicable: {}\nAvailable assists: {}", 49 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
50 assist_id, 50 assist_id,
51 Assist::resolved(&db, frange) 51 Assist::resolved(&db, &AssistConfig::default(), frange)
52 .into_iter() 52 .into_iter()
53 .map(|assist| assist.assist.id.0) 53 .map(|assist| assist.assist.id.0)
54 .collect::<Vec<_>>() 54 .collect::<Vec<_>>()
@@ -90,7 +90,8 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult) {
90 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; 90 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
91 91
92 let sema = Semantics::new(&db); 92 let sema = Semantics::new(&db);
93 let ctx = AssistContext::new(sema, frange); 93 let config = AssistConfig::default();
94 let ctx = AssistContext::new(sema, &config, frange);
94 let mut acc = Assists::new_resolved(&ctx); 95 let mut acc = Assists::new_resolved(&ctx);
95 handler(&mut acc, &ctx); 96 handler(&mut acc, &ctx);
96 let mut res = acc.finish_resolved(); 97 let mut res = acc.finish_resolved();
@@ -103,19 +104,20 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult) {
103 let mut actual = db.file_text(change.file_id).as_ref().to_owned(); 104 let mut actual = db.file_text(change.file_id).as_ref().to_owned();
104 change.edit.apply(&mut actual); 105 change.edit.apply(&mut actual);
105 106
106 match source_change.cursor_position { 107 if !source_change.is_snippet {
107 None => { 108 match source_change.cursor_position {
108 if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { 109 None => {
109 let off = change 110 if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset {
110 .edit 111 let off = change
111 .apply_to_offset(before_cursor_pos) 112 .edit
112 .expect("cursor position is affected by the edit"); 113 .apply_to_offset(before_cursor_pos)
113 actual = add_cursor(&actual, off) 114 .expect("cursor position is affected by the edit");
115 actual = add_cursor(&actual, off)
116 }
114 } 117 }
115 } 118 Some(off) => actual = add_cursor(&actual, off.offset),
116 Some(off) => actual = add_cursor(&actual, off.offset), 119 };
117 }; 120 }
118
119 assert_eq_text!(after, &actual); 121 assert_eq_text!(after, &actual);
120 } 122 }
121 (Some(assist), ExpectedResult::Target(target)) => { 123 (Some(assist), ExpectedResult::Target(target)) => {
@@ -136,7 +138,7 @@ fn assist_order_field_struct() {
136 let (before_cursor_pos, before) = extract_offset(before); 138 let (before_cursor_pos, before) = extract_offset(before);
137 let (db, file_id) = with_single_file(&before); 139 let (db, file_id) = with_single_file(&before);
138 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; 140 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
139 let assists = Assist::resolved(&db, frange); 141 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
140 let mut assists = assists.iter(); 142 let mut assists = assists.iter();
141 143
142 assert_eq!( 144 assert_eq!(
@@ -159,7 +161,7 @@ fn assist_order_if_expr() {
159 let (range, before) = extract_range(before); 161 let (range, before) = extract_range(before);
160 let (db, file_id) = with_single_file(&before); 162 let (db, file_id) = with_single_file(&before);
161 let frange = FileRange { file_id, range }; 163 let frange = FileRange { file_id, range };
162 let assists = Assist::resolved(&db, frange); 164 let assists = Assist::resolved(&db, &AssistConfig::default(), frange);
163 let mut assists = assists.iter(); 165 let mut assists = assists.iter();
164 166
165 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable"); 167 assert_eq!(assists.next().expect("expected assist").assist.label, "Extract into variable");
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs
index 8bdc43b1a..191300704 100644
--- a/crates/ra_ide/src/completion.rs
+++ b/crates/ra_ide/src/completion.rs
@@ -59,8 +59,8 @@ pub use crate::completion::{
59/// with ordering of completions (currently this is done by the client). 59/// with ordering of completions (currently this is done by the client).
60pub(crate) fn completions( 60pub(crate) fn completions(
61 db: &RootDatabase, 61 db: &RootDatabase,
62 position: FilePosition,
63 config: &CompletionConfig, 62 config: &CompletionConfig,
63 position: FilePosition,
64) -> Option<Completions> { 64) -> Option<Completions> {
65 let ctx = CompletionContext::new(db, position, config)?; 65 let ctx = CompletionContext::new(db, position, config)?;
66 66
diff --git a/crates/ra_ide/src/completion/test_utils.rs b/crates/ra_ide/src/completion/test_utils.rs
index eb90b5279..bf22452a2 100644
--- a/crates/ra_ide/src/completion/test_utils.rs
+++ b/crates/ra_ide/src/completion/test_utils.rs
@@ -20,7 +20,7 @@ pub(crate) fn do_completion_with_options(
20 } else { 20 } else {
21 single_file_with_position(code) 21 single_file_with_position(code)
22 }; 22 };
23 let completions = analysis.completions(position, options).unwrap().unwrap(); 23 let completions = analysis.completions(options, position).unwrap().unwrap();
24 let completion_items: Vec<CompletionItem> = completions.into(); 24 let completion_items: Vec<CompletionItem> = completions.into();
25 let mut kind_completions: Vec<CompletionItem> = 25 let mut kind_completions: Vec<CompletionItem> =
26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect(); 26 completion_items.into_iter().filter(|c| c.completion_kind == kind).collect();
diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs
index 87a0b80f1..54c2bcc09 100644
--- a/crates/ra_ide/src/diagnostics.rs
+++ b/crates/ra_ide/src/diagnostics.rs
@@ -629,6 +629,7 @@ mod tests {
629 }, 629 },
630 ], 630 ],
631 cursor_position: None, 631 cursor_position: None,
632 is_snippet: false,
632 }, 633 },
633 ), 634 ),
634 severity: Error, 635 severity: Error,
@@ -685,6 +686,7 @@ mod tests {
685 ], 686 ],
686 file_system_edits: [], 687 file_system_edits: [],
687 cursor_position: None, 688 cursor_position: None,
689 is_snippet: false,
688 }, 690 },
689 ), 691 ),
690 severity: Error, 692 severity: Error,
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs
index 78149ddfc..66125f2f5 100644
--- a/crates/ra_ide/src/lib.rs
+++ b/crates/ra_ide/src/lib.rs
@@ -82,7 +82,7 @@ pub use crate::{
82}; 82};
83 83
84pub use hir::Documentation; 84pub use hir::Documentation;
85pub use ra_assists::AssistId; 85pub use ra_assists::{AssistConfig, AssistId};
86pub use ra_db::{ 86pub use ra_db::{
87 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId, 87 Canceled, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRootId,
88}; 88};
@@ -458,17 +458,17 @@ impl Analysis {
458 /// Computes completions at the given position. 458 /// Computes completions at the given position.
459 pub fn completions( 459 pub fn completions(
460 &self, 460 &self,
461 position: FilePosition,
462 config: &CompletionConfig, 461 config: &CompletionConfig,
462 position: FilePosition,
463 ) -> Cancelable<Option<Vec<CompletionItem>>> { 463 ) -> Cancelable<Option<Vec<CompletionItem>>> {
464 self.with_db(|db| completion::completions(db, position, config).map(Into::into)) 464 self.with_db(|db| completion::completions(db, config, position).map(Into::into))
465 } 465 }
466 466
467 /// Computes assists (aka code actions aka intentions) for the given 467 /// Computes assists (aka code actions aka intentions) for the given
468 /// position. 468 /// position.
469 pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<Assist>> { 469 pub fn assists(&self, config: &AssistConfig, frange: FileRange) -> Cancelable<Vec<Assist>> {
470 self.with_db(|db| { 470 self.with_db(|db| {
471 ra_assists::Assist::resolved(db, frange) 471 ra_assists::Assist::resolved(db, config, frange)
472 .into_iter() 472 .into_iter()
473 .map(|assist| Assist { 473 .map(|assist| Assist {
474 id: assist.assist.id, 474 id: assist.assist.id,
diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs
index 410dae75c..68a53ad4b 100644
--- a/crates/ra_ide/src/references/rename.rs
+++ b/crates/ra_ide/src/references/rename.rs
@@ -670,6 +670,7 @@ mod tests {
670 }, 670 },
671 ], 671 ],
672 cursor_position: None, 672 cursor_position: None,
673 is_snippet: false,
673 }, 674 },
674 }, 675 },
675 ) 676 )
@@ -722,6 +723,7 @@ mod tests {
722 }, 723 },
723 ], 724 ],
724 cursor_position: None, 725 cursor_position: None,
726 is_snippet: false,
725 }, 727 },
726 }, 728 },
727 ) 729 )
@@ -818,6 +820,7 @@ mod tests {
818 }, 820 },
819 ], 821 ],
820 cursor_position: None, 822 cursor_position: None,
823 is_snippet: false,
821 }, 824 },
822 }, 825 },
823 ) 826 )
diff --git a/crates/ra_ide_db/src/source_change.rs b/crates/ra_ide_db/src/source_change.rs
index af81a91a4..c64165f3a 100644
--- a/crates/ra_ide_db/src/source_change.rs
+++ b/crates/ra_ide_db/src/source_change.rs
@@ -13,6 +13,7 @@ pub struct SourceChange {
13 pub source_file_edits: Vec<SourceFileEdit>, 13 pub source_file_edits: Vec<SourceFileEdit>,
14 pub file_system_edits: Vec<FileSystemEdit>, 14 pub file_system_edits: Vec<FileSystemEdit>,
15 pub cursor_position: Option<FilePosition>, 15 pub cursor_position: Option<FilePosition>,
16 pub is_snippet: bool,
16} 17}
17 18
18impl SourceChange { 19impl SourceChange {
@@ -28,6 +29,7 @@ impl SourceChange {
28 source_file_edits, 29 source_file_edits,
29 file_system_edits, 30 file_system_edits,
30 cursor_position: None, 31 cursor_position: None,
32 is_snippet: false,
31 } 33 }
32 } 34 }
33 35
@@ -41,6 +43,7 @@ impl SourceChange {
41 source_file_edits: edits, 43 source_file_edits: edits,
42 file_system_edits: vec![], 44 file_system_edits: vec![],
43 cursor_position: None, 45 cursor_position: None,
46 is_snippet: false,
44 } 47 }
45 } 48 }
46 49
@@ -52,6 +55,7 @@ impl SourceChange {
52 source_file_edits: vec![], 55 source_file_edits: vec![],
53 file_system_edits: edits, 56 file_system_edits: edits,
54 cursor_position: None, 57 cursor_position: None,
58 is_snippet: false,
55 } 59 }
56 } 60 }
57 61
@@ -115,6 +119,7 @@ impl SingleFileChange {
115 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }], 119 source_file_edits: vec![SourceFileEdit { file_id, edit: self.edit }],
116 file_system_edits: Vec::new(), 120 file_system_edits: Vec::new(),
117 cursor_position: self.cursor_position.map(|offset| FilePosition { file_id, offset }), 121 cursor_position: self.cursor_position.map(|offset| FilePosition { file_id, offset }),
122 is_snippet: false,
118 } 123 }
119 } 124 }
120} 125}
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 6147ae207..b20efe98d 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -105,7 +105,7 @@ pub fn analysis_bench(
105 if is_completion { 105 if is_completion {
106 let options = CompletionConfig::default(); 106 let options = CompletionConfig::default();
107 let res = do_work(&mut host, file_id, |analysis| { 107 let res = do_work(&mut host, file_id, |analysis| {
108 analysis.completions(file_position, &options) 108 analysis.completions(&options, file_position)
109 }); 109 });
110 if verbosity.is_verbose() { 110 if verbosity.is_verbose() {
111 println!("\n{:#?}", res); 111 println!("\n{:#?}", res);
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index b5dc6f0fa..063b1b316 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -11,7 +11,7 @@ use std::{ffi::OsString, path::PathBuf};
11 11
12use lsp_types::ClientCapabilities; 12use lsp_types::ClientCapabilities;
13use ra_flycheck::FlycheckConfig; 13use ra_flycheck::FlycheckConfig;
14use ra_ide::{CompletionConfig, InlayHintsConfig}; 14use ra_ide::{AssistConfig, CompletionConfig, InlayHintsConfig};
15use ra_project_model::CargoConfig; 15use ra_project_model::CargoConfig;
16use serde::Deserialize; 16use serde::Deserialize;
17 17
@@ -32,6 +32,7 @@ pub struct Config {
32 32
33 pub inlay_hints: InlayHintsConfig, 33 pub inlay_hints: InlayHintsConfig,
34 pub completion: CompletionConfig, 34 pub completion: CompletionConfig,
35 pub assist: AssistConfig,
35 pub call_info_full: bool, 36 pub call_info_full: bool,
36 pub lens: LensConfig, 37 pub lens: LensConfig,
37} 38}
@@ -136,6 +137,7 @@ impl Default for Config {
136 add_call_argument_snippets: true, 137 add_call_argument_snippets: true,
137 ..CompletionConfig::default() 138 ..CompletionConfig::default()
138 }, 139 },
140 assist: AssistConfig::default(),
139 call_info_full: true, 141 call_info_full: true,
140 lens: LensConfig::default(), 142 lens: LensConfig::default(),
141 } 143 }
@@ -281,6 +283,7 @@ impl Config {
281 } 283 }
282 } 284 }
283 } 285 }
286 self.assist.allow_snippets(false);
284 } 287 }
285 288
286 if let Some(window_caps) = caps.window.as_ref() { 289 if let Some(window_caps) = caps.window.as_ref() {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index e67556752..13ae061fa 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -476,7 +476,7 @@ pub fn handle_completion(
476 return Ok(None); 476 return Ok(None);
477 } 477 }
478 478
479 let items = match world.analysis().completions(position, &world.config.completion)? { 479 let items = match world.analysis().completions(&world.config.completion, position)? {
480 None => return Ok(None), 480 None => return Ok(None),
481 Some(items) => items, 481 Some(items) => items,
482 }; 482 };
@@ -740,7 +740,9 @@ pub fn handle_code_action(
740 } 740 }
741 741
742 let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default(); 742 let mut grouped_assists: FxHashMap<String, (usize, Vec<Assist>)> = FxHashMap::default();
743 for assist in world.analysis().assists(FileRange { file_id, range })?.into_iter() { 743 for assist in
744 world.analysis().assists(&world.config.assist, FileRange { file_id, range })?.into_iter()
745 {
744 match &assist.group_label { 746 match &assist.group_label {
745 Some(label) => grouped_assists 747 Some(label) => grouped_assists
746 .entry(label.to_owned()) 748 .entry(label.to_owned())