aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/assists/src/assist_config.rs32
-rw-r--r--crates/assists/src/assist_context.rs10
-rw-r--r--crates/assists/src/handlers/generate_function.rs3
-rw-r--r--crates/assists/src/lib.rs2
-rw-r--r--crates/assists/src/tests.rs38
-rw-r--r--crates/assists/src/utils.rs7
-rw-r--r--crates/completion/src/completions/postfix.rs5
-rw-r--r--crates/completion/src/completions/postfix/format_like.rs7
-rw-r--r--crates/completion/src/completions/snippet.rs6
-rw-r--r--crates/completion/src/completions/unqualified_path.rs18
-rw-r--r--crates/completion/src/config.rs26
-rw-r--r--crates/completion/src/item.rs4
-rw-r--r--crates/completion/src/lib.rs7
-rw-r--r--crates/completion/src/render.rs12
-rw-r--r--crates/completion/src/render/function.rs4
-rw-r--r--crates/completion/src/render/pattern.rs6
-rw-r--r--crates/completion/src/test_utils.rs22
-rw-r--r--crates/ide/src/lib.rs2
-rw-r--r--crates/ide_db/src/helpers.rs20
-rw-r--r--crates/rust-analyzer/src/cli/analysis_bench.rs18
-rw-r--r--crates/rust-analyzer/src/config.rs67
-rw-r--r--crates/rust-analyzer/src/to_proto.rs10
22 files changed, 164 insertions, 162 deletions
diff --git a/crates/assists/src/assist_config.rs b/crates/assists/src/assist_config.rs
index c458d9054..4fe8ea761 100644
--- a/crates/assists/src/assist_config.rs
+++ b/crates/assists/src/assist_config.rs
@@ -4,8 +4,7 @@
4//! module, and we use to statically check that we only produce snippet 4//! module, and we use to statically check that we only produce snippet
5//! assists if we are allowed to. 5//! assists if we are allowed to.
6 6
7use hir::PrefixKind; 7use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap};
8use ide_db::helpers::insert_use::MergeBehavior;
9 8
10use crate::AssistKind; 9use crate::AssistKind;
11 10
@@ -16,35 +15,8 @@ pub struct AssistConfig {
16 pub insert_use: InsertUseConfig, 15 pub insert_use: InsertUseConfig,
17} 16}
18 17
19impl AssistConfig {
20 pub fn allow_snippets(&mut self, yes: bool) {
21 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
22 }
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26pub struct SnippetCap {
27 _private: (),
28}
29
30impl Default for AssistConfig {
31 fn default() -> Self {
32 AssistConfig {
33 snippet_cap: Some(SnippetCap { _private: () }),
34 allowed: None,
35 insert_use: InsertUseConfig::default(),
36 }
37 }
38}
39
40#[derive(Clone, Copy, Debug, PartialEq, Eq)] 18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
41pub struct InsertUseConfig { 19pub struct InsertUseConfig {
42 pub merge: Option<MergeBehavior>, 20 pub merge: Option<MergeBehavior>,
43 pub prefix_kind: PrefixKind, 21 pub prefix_kind: hir::PrefixKind,
44}
45
46impl Default for InsertUseConfig {
47 fn default() -> Self {
48 InsertUseConfig { merge: Some(MergeBehavior::Full), prefix_kind: PrefixKind::Plain }
49 }
50} 22}
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 4f59d39a9..91cc63427 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -4,7 +4,10 @@ use std::mem;
4 4
5use algo::find_covering_element; 5use algo::find_covering_element;
6use hir::Semantics; 6use hir::Semantics;
7use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange}; 7use ide_db::{
8 base_db::{AnchoredPathBuf, FileId, FileRange},
9 helpers::SnippetCap,
10};
8use ide_db::{ 11use ide_db::{
9 label::Label, 12 label::Label,
10 source_change::{FileSystemEdit, SourceChange, SourceFileEdit}, 13 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
@@ -17,10 +20,7 @@ use syntax::{
17}; 20};
18use text_edit::{TextEdit, TextEditBuilder}; 21use text_edit::{TextEdit, TextEditBuilder};
19 22
20use crate::{ 23use crate::{assist_config::AssistConfig, Assist, AssistId, AssistKind, GroupLabel};
21 assist_config::{AssistConfig, SnippetCap},
22 Assist, AssistId, AssistKind, GroupLabel,
23};
24 24
25/// `AssistContext` allows to apply an assist or check if it could be applied. 25/// `AssistContext` allows to apply an assist or check if it could be applied.
26/// 26///
diff --git a/crates/assists/src/handlers/generate_function.rs b/crates/assists/src/handlers/generate_function.rs
index f4cf155b6..d169abedb 100644
--- a/crates/assists/src/handlers/generate_function.rs
+++ b/crates/assists/src/handlers/generate_function.rs
@@ -1,5 +1,5 @@
1use hir::HirDisplay; 1use hir::HirDisplay;
2use ide_db::base_db::FileId; 2use ide_db::{base_db::FileId, helpers::SnippetCap};
3use rustc_hash::{FxHashMap, FxHashSet}; 3use rustc_hash::{FxHashMap, FxHashSet};
4use syntax::{ 4use syntax::{
5 ast::{ 5 ast::{
@@ -11,7 +11,6 @@ use syntax::{
11}; 11};
12 12
13use crate::{ 13use crate::{
14 assist_config::SnippetCap,
15 utils::{render_snippet, Cursor}, 14 utils::{render_snippet, Cursor},
16 AssistContext, AssistId, AssistKind, Assists, 15 AssistContext, AssistId, AssistKind, Assists,
17}; 16};
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index 5e3a1b368..90009c55a 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -24,7 +24,7 @@ use syntax::TextRange;
24 24
25pub(crate) use crate::assist_context::{AssistContext, Assists}; 25pub(crate) use crate::assist_context::{AssistContext, Assists};
26 26
27pub use assist_config::AssistConfig; 27pub use assist_config::{AssistConfig, InsertUseConfig};
28 28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)] 29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub enum AssistKind { 30pub enum AssistKind {
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
index 21e448fb8..a4c6a7570 100644
--- a/crates/assists/src/tests.rs
+++ b/crates/assists/src/tests.rs
@@ -1,15 +1,29 @@
1mod generated; 1mod generated;
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; 4use ide_db::{
5use ide_db::source_change::FileSystemEdit; 5 base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt},
6use ide_db::RootDatabase; 6 helpers::{insert_use::MergeBehavior, SnippetCap},
7 source_change::FileSystemEdit,
8 RootDatabase,
9};
7use syntax::TextRange; 10use syntax::TextRange;
8use test_utils::{assert_eq_text, extract_offset, extract_range}; 11use test_utils::{assert_eq_text, extract_offset, extract_range};
9 12
10use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; 13use crate::{
14 handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists, InsertUseConfig,
15};
11use stdx::{format_to, trim_indent}; 16use stdx::{format_to, trim_indent};
12 17
18pub(crate) const TEST_CONFIG: AssistConfig = AssistConfig {
19 snippet_cap: SnippetCap::new(true),
20 allowed: None,
21 insert_use: InsertUseConfig {
22 merge: Some(MergeBehavior::Full),
23 prefix_kind: hir::PrefixKind::Plain,
24 },
25};
26
13pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { 27pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) {
14 RootDatabase::with_single_file(text) 28 RootDatabase::with_single_file(text)
15} 29}
@@ -48,14 +62,14 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
48 let before = db.file_text(file_id).to_string(); 62 let before = db.file_text(file_id).to_string();
49 let frange = FileRange { file_id, range: selection.into() }; 63 let frange = FileRange { file_id, range: selection.into() };
50 64
51 let assist = Assist::get(&db, &AssistConfig::default(), true, frange) 65 let assist = Assist::get(&db, &TEST_CONFIG, true, frange)
52 .into_iter() 66 .into_iter()
53 .find(|assist| assist.id.0 == assist_id) 67 .find(|assist| assist.id.0 == assist_id)
54 .unwrap_or_else(|| { 68 .unwrap_or_else(|| {
55 panic!( 69 panic!(
56 "\n\nAssist is not applicable: {}\nAvailable assists: {}", 70 "\n\nAssist is not applicable: {}\nAvailable assists: {}",
57 assist_id, 71 assist_id,
58 Assist::get(&db, &AssistConfig::default(), false, frange) 72 Assist::get(&db, &TEST_CONFIG, false, frange)
59 .into_iter() 73 .into_iter()
60 .map(|assist| assist.id.0) 74 .map(|assist| assist.id.0)
61 .collect::<Vec<_>>() 75 .collect::<Vec<_>>()
@@ -89,7 +103,7 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
89 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() }; 103 let frange = FileRange { file_id: file_with_caret_id, range: range_or_offset.into() };
90 104
91 let sema = Semantics::new(&db); 105 let sema = Semantics::new(&db);
92 let config = AssistConfig::default(); 106 let config = TEST_CONFIG;
93 let ctx = AssistContext::new(sema, &config, frange); 107 let ctx = AssistContext::new(sema, &config, frange);
94 let mut acc = Assists::new(&ctx, true); 108 let mut acc = Assists::new(&ctx, true);
95 handler(&mut acc, &ctx); 109 handler(&mut acc, &ctx);
@@ -156,7 +170,7 @@ fn assist_order_field_struct() {
156 let (before_cursor_pos, before) = extract_offset(before); 170 let (before_cursor_pos, before) = extract_offset(before);
157 let (db, file_id) = with_single_file(&before); 171 let (db, file_id) = with_single_file(&before);
158 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) }; 172 let frange = FileRange { file_id, range: TextRange::empty(before_cursor_pos) };
159 let assists = Assist::get(&db, &AssistConfig::default(), false, frange); 173 let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
160 let mut assists = assists.iter(); 174 let mut assists = assists.iter();
161 175
162 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)"); 176 assert_eq!(assists.next().expect("expected assist").label, "Change visibility to pub(crate)");
@@ -176,7 +190,7 @@ fn assist_order_if_expr() {
176 let (range, before) = extract_range(before); 190 let (range, before) = extract_range(before);
177 let (db, file_id) = with_single_file(&before); 191 let (db, file_id) = with_single_file(&before);
178 let frange = FileRange { file_id, range }; 192 let frange = FileRange { file_id, range };
179 let assists = Assist::get(&db, &AssistConfig::default(), false, frange); 193 let assists = Assist::get(&db, &TEST_CONFIG, false, frange);
180 let mut assists = assists.iter(); 194 let mut assists = assists.iter();
181 195
182 assert_eq!(assists.next().expect("expected assist").label, "Extract into variable"); 196 assert_eq!(assists.next().expect("expected assist").label, "Extract into variable");
@@ -198,7 +212,7 @@ fn assist_filter_works() {
198 let frange = FileRange { file_id, range }; 212 let frange = FileRange { file_id, range };
199 213
200 { 214 {
201 let mut cfg = AssistConfig::default(); 215 let mut cfg = TEST_CONFIG;
202 cfg.allowed = Some(vec![AssistKind::Refactor]); 216 cfg.allowed = Some(vec![AssistKind::Refactor]);
203 217
204 let assists = Assist::get(&db, &cfg, false, frange); 218 let assists = Assist::get(&db, &cfg, false, frange);
@@ -209,7 +223,7 @@ fn assist_filter_works() {
209 } 223 }
210 224
211 { 225 {
212 let mut cfg = AssistConfig::default(); 226 let mut cfg = TEST_CONFIG;
213 cfg.allowed = Some(vec![AssistKind::RefactorExtract]); 227 cfg.allowed = Some(vec![AssistKind::RefactorExtract]);
214 let assists = Assist::get(&db, &cfg, false, frange); 228 let assists = Assist::get(&db, &cfg, false, frange);
215 assert_eq!(assists.len(), 1); 229 assert_eq!(assists.len(), 1);
@@ -219,7 +233,7 @@ fn assist_filter_works() {
219 } 233 }
220 234
221 { 235 {
222 let mut cfg = AssistConfig::default(); 236 let mut cfg = TEST_CONFIG;
223 cfg.allowed = Some(vec![AssistKind::QuickFix]); 237 cfg.allowed = Some(vec![AssistKind::QuickFix]);
224 let assists = Assist::get(&db, &cfg, false, frange); 238 let assists = Assist::get(&db, &cfg, false, frange);
225 assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out"); 239 assert!(assists.is_empty(), "All asserts but quickfixes should be filtered out");
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index 8212cd129..9ea96eb73 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -4,7 +4,7 @@ pub(crate) mod import_assets;
4use std::ops; 4use std::ops;
5 5
6use hir::HasSource; 6use hir::HasSource;
7use ide_db::RootDatabase; 7use ide_db::{helpers::SnippetCap, RootDatabase};
8use itertools::Itertools; 8use itertools::Itertools;
9use syntax::{ 9use syntax::{
10 ast::edit::AstNodeEdit, 10 ast::edit::AstNodeEdit,
@@ -16,10 +16,7 @@ use syntax::{
16 SyntaxNode, TextSize, T, 16 SyntaxNode, TextSize, T,
17}; 17};
18 18
19use crate::{ 19use crate::ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams};
20 assist_config::SnippetCap,
21 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
22};
23 20
24pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr { 21pub(crate) fn unwrap_trivial_block(block: ast::BlockExpr) -> ast::Expr {
25 extract_trivial_expression(&block) 22 extract_trivial_expression(&block)
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index 3883d6d21..4888f518a 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -2,7 +2,7 @@
2 2
3mod format_like; 3mod format_like;
4 4
5use ide_db::ty_filter::TryEnum; 5use ide_db::{helpers::SnippetCap, ty_filter::TryEnum};
6use syntax::{ 6use syntax::{
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8 SyntaxKind::{BLOCK_EXPR, EXPR_STMT}, 8 SyntaxKind::{BLOCK_EXPR, EXPR_STMT},
@@ -10,9 +10,8 @@ use syntax::{
10}; 10};
11use text_edit::TextEdit; 11use text_edit::TextEdit;
12 12
13use self::format_like::add_format_like_completions;
14use crate::{ 13use crate::{
15 config::SnippetCap, 14 completions::postfix::format_like::add_format_like_completions,
16 context::CompletionContext, 15 context::CompletionContext,
17 item::{Builder, CompletionKind}, 16 item::{Builder, CompletionKind},
18 CompletionItem, CompletionItemKind, Completions, 17 CompletionItem, CompletionItemKind, Completions,
diff --git a/crates/completion/src/completions/postfix/format_like.rs b/crates/completion/src/completions/postfix/format_like.rs
index def4b13fb..3afc63021 100644
--- a/crates/completion/src/completions/postfix/format_like.rs
+++ b/crates/completion/src/completions/postfix/format_like.rs
@@ -14,12 +14,11 @@
14// + `logw` -> `log::warn!(...)` 14// + `logw` -> `log::warn!(...)`
15// + `loge` -> `log::error!(...)` 15// + `loge` -> `log::error!(...)`
16 16
17use crate::{ 17use ide_db::helpers::SnippetCap;
18 completions::postfix::postfix_snippet, config::SnippetCap, context::CompletionContext,
19 Completions,
20};
21use syntax::ast::{self, AstToken}; 18use syntax::ast::{self, AstToken};
22 19
20use crate::{completions::postfix::postfix_snippet, context::CompletionContext, Completions};
21
23/// Mapping ("postfix completion item" => "macro to use") 22/// Mapping ("postfix completion item" => "macro to use")
24static KINDS: &[(&str, &str)] = &[ 23static KINDS: &[(&str, &str)] = &[
25 ("format", "format!"), 24 ("format", "format!"),
diff --git a/crates/completion/src/completions/snippet.rs b/crates/completion/src/completions/snippet.rs
index 842590130..b5e704696 100644
--- a/crates/completion/src/completions/snippet.rs
+++ b/crates/completion/src/completions/snippet.rs
@@ -1,8 +1,10 @@
1//! This file provides snippet completions, like `pd` => `eprintln!(...)`. 1//! This file provides snippet completions, like `pd` => `eprintln!(...)`.
2 2
3use ide_db::helpers::SnippetCap;
4
3use crate::{ 5use crate::{
4 config::SnippetCap, item::Builder, CompletionContext, CompletionItem, CompletionItemKind, 6 item::Builder, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
5 CompletionKind, Completions, 7 Completions,
6}; 8};
7 9
8fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { 10fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder {
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 896f167ff..2da21b5c2 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -192,12 +192,14 @@ mod tests {
192 use test_utils::mark; 192 use test_utils::mark;
193 193
194 use crate::{ 194 use crate::{
195 test_utils::{check_edit, check_edit_with_config, completion_list_with_config}, 195 test_utils::{
196 check_edit, check_edit_with_config, completion_list_with_config, TEST_CONFIG,
197 },
196 CompletionConfig, CompletionKind, 198 CompletionConfig, CompletionKind,
197 }; 199 };
198 200
199 fn check(ra_fixture: &str, expect: Expect) { 201 fn check(ra_fixture: &str, expect: Expect) {
200 check_with_config(CompletionConfig::default(), ra_fixture, expect); 202 check_with_config(TEST_CONFIG, ra_fixture, expect);
201 } 203 }
202 204
203 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { 205 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
@@ -205,10 +207,6 @@ mod tests {
205 expect.assert_eq(&actual) 207 expect.assert_eq(&actual)
206 } 208 }
207 209
208 fn fuzzy_completion_config() -> CompletionConfig {
209 CompletionConfig::default()
210 }
211
212 #[test] 210 #[test]
213 fn self_fulfilling_completion() { 211 fn self_fulfilling_completion() {
214 mark::check!(self_fulfilling_completion); 212 mark::check!(self_fulfilling_completion);
@@ -832,7 +830,7 @@ impl My<|>
832 #[test] 830 #[test]
833 fn function_fuzzy_completion() { 831 fn function_fuzzy_completion() {
834 check_edit_with_config( 832 check_edit_with_config(
835 fuzzy_completion_config(), 833 TEST_CONFIG,
836 "stdin", 834 "stdin",
837 r#" 835 r#"
838//- /lib.rs crate:dep 836//- /lib.rs crate:dep
@@ -858,7 +856,7 @@ fn main() {
858 #[test] 856 #[test]
859 fn macro_fuzzy_completion() { 857 fn macro_fuzzy_completion() {
860 check_edit_with_config( 858 check_edit_with_config(
861 fuzzy_completion_config(), 859 TEST_CONFIG,
862 "macro_with_curlies!", 860 "macro_with_curlies!",
863 r#" 861 r#"
864//- /lib.rs crate:dep 862//- /lib.rs crate:dep
@@ -886,7 +884,7 @@ fn main() {
886 #[test] 884 #[test]
887 fn struct_fuzzy_completion() { 885 fn struct_fuzzy_completion() {
888 check_edit_with_config( 886 check_edit_with_config(
889 fuzzy_completion_config(), 887 TEST_CONFIG,
890 "ThirdStruct", 888 "ThirdStruct",
891 r#" 889 r#"
892//- /lib.rs crate:dep 890//- /lib.rs crate:dep
@@ -917,7 +915,7 @@ fn main() {
917 fn fuzzy_completions_come_in_specific_order() { 915 fn fuzzy_completions_come_in_specific_order() {
918 mark::check!(certain_fuzzy_order_test); 916 mark::check!(certain_fuzzy_order_test);
919 check_with_config( 917 check_with_config(
920 fuzzy_completion_config(), 918 TEST_CONFIG,
921 r#" 919 r#"
922//- /lib.rs crate:dep 920//- /lib.rs crate:dep
923pub struct FirstStruct; 921pub struct FirstStruct;
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index 9f82b0346..b4439b7d1 100644
--- a/crates/completion/src/config.rs
+++ b/crates/completion/src/config.rs
@@ -4,7 +4,7 @@
4//! module, and we use to statically check that we only produce snippet 4//! module, and we use to statically check that we only produce snippet
5//! completions if we are allowed to. 5//! completions if we are allowed to.
6 6
7use ide_db::helpers::insert_use::MergeBehavior; 7use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap};
8 8
9#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct CompletionConfig { 10pub struct CompletionConfig {
@@ -15,27 +15,3 @@ pub struct CompletionConfig {
15 pub snippet_cap: Option<SnippetCap>, 15 pub snippet_cap: Option<SnippetCap>,
16 pub merge: Option<MergeBehavior>, 16 pub merge: Option<MergeBehavior>,
17} 17}
18
19impl CompletionConfig {
20 pub fn allow_snippets(&mut self, yes: bool) {
21 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
22 }
23}
24
25#[derive(Clone, Copy, Debug, PartialEq, Eq)]
26pub struct SnippetCap {
27 _private: (),
28}
29
30impl Default for CompletionConfig {
31 fn default() -> Self {
32 CompletionConfig {
33 enable_postfix_completions: true,
34 enable_autoimport_completions: true,
35 add_call_parenthesis: true,
36 add_call_argument_snippets: true,
37 snippet_cap: Some(SnippetCap { _private: () }),
38 merge: Some(MergeBehavior::Full),
39 }
40 }
41}
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 65f8353e7..7087fae37 100644
--- a/crates/completion/src/item.rs
+++ b/crates/completion/src/item.rs
@@ -5,13 +5,11 @@ use std::fmt;
5use hir::{Documentation, ModPath, Mutability}; 5use hir::{Documentation, ModPath, Mutability};
6use ide_db::helpers::{ 6use ide_db::helpers::{
7 insert_use::{self, ImportScope, MergeBehavior}, 7 insert_use::{self, ImportScope, MergeBehavior},
8 mod_path_to_ast, 8 mod_path_to_ast, SnippetCap,
9}; 9};
10use syntax::{algo, TextRange}; 10use syntax::{algo, TextRange};
11use text_edit::TextEdit; 11use text_edit::TextEdit;
12 12
13use crate::config::SnippetCap;
14
15/// `CompletionItem` describes a single completion variant in the editor pop-up. 13/// `CompletionItem` describes a single completion variant in the editor pop-up.
16/// It is basically a POD with various properties. To construct a 14/// It is basically a POD with various properties. To construct a
17/// `CompletionItem`, use `new` method and the `Builder` struct. 15/// `CompletionItem`, use `new` method and the `Builder` struct.
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index 366aced71..3c7d5a46c 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -158,8 +158,7 @@ pub fn resolve_completion_edits(
158 158
159#[cfg(test)] 159#[cfg(test)]
160mod tests { 160mod tests {
161 use crate::config::CompletionConfig; 161 use crate::test_utils::{self, TEST_CONFIG};
162 use crate::test_utils;
163 162
164 struct DetailAndDocumentation<'a> { 163 struct DetailAndDocumentation<'a> {
165 detail: &'a str, 164 detail: &'a str,
@@ -168,7 +167,7 @@ mod tests {
168 167
169 fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) { 168 fn check_detail_and_documentation(ra_fixture: &str, expected: DetailAndDocumentation) {
170 let (db, position) = test_utils::position(ra_fixture); 169 let (db, position) = test_utils::position(ra_fixture);
171 let config = CompletionConfig::default(); 170 let config = TEST_CONFIG;
172 let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into(); 171 let completions: Vec<_> = crate::completions(&db, &config, position).unwrap().into();
173 for item in completions { 172 for item in completions {
174 if item.detail() == Some(expected.detail) { 173 if item.detail() == Some(expected.detail) {
@@ -183,7 +182,7 @@ mod tests {
183 182
184 fn check_no_completion(ra_fixture: &str) { 183 fn check_no_completion(ra_fixture: &str) {
185 let (db, position) = test_utils::position(ra_fixture); 184 let (db, position) = test_utils::position(ra_fixture);
186 let config = CompletionConfig::default(); 185 let config = TEST_CONFIG;
187 186
188 let completions: Option<Vec<String>> = crate::completions(&db, &config, position) 187 let completions: Option<Vec<String>> = crate::completions(&db, &config, position)
189 .and_then(|completions| { 188 .and_then(|completions| {
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index ac0b2a513..7554c1565 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -11,13 +11,13 @@ pub(crate) mod type_alias;
11mod builder_ext; 11mod builder_ext;
12 12
13use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type}; 13use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type};
14use ide_db::RootDatabase; 14use ide_db::{helpers::SnippetCap, RootDatabase};
15use syntax::TextRange; 15use syntax::TextRange;
16use test_utils::mark; 16use test_utils::mark;
17 17
18use crate::{ 18use crate::{
19 config::SnippetCap, item::ImportEdit, CompletionContext, CompletionItem, CompletionItemKind, 19 item::ImportEdit, CompletionContext, CompletionItem, CompletionItemKind, CompletionKind,
20 CompletionKind, CompletionScore, 20 CompletionScore,
21}; 21};
22 22
23use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro}; 23use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro};
@@ -320,8 +320,8 @@ mod tests {
320 use test_utils::mark; 320 use test_utils::mark;
321 321
322 use crate::{ 322 use crate::{
323 test_utils::{check_edit, do_completion, get_all_items}, 323 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
324 CompletionConfig, CompletionKind, CompletionScore, 324 CompletionKind, CompletionScore,
325 }; 325 };
326 326
327 fn check(ra_fixture: &str, expect: Expect) { 327 fn check(ra_fixture: &str, expect: Expect) {
@@ -338,7 +338,7 @@ mod tests {
338 } 338 }
339 } 339 }
340 340
341 let mut completions = get_all_items(CompletionConfig::default(), ra_fixture); 341 let mut completions = get_all_items(TEST_CONFIG, ra_fixture);
342 completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string())); 342 completions.sort_by_key(|it| (Reverse(it.score()), it.label().to_string()));
343 let actual = completions 343 let actual = completions
344 .into_iter() 344 .into_iter()
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 081be14f4..7b2f62b4b 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -113,7 +113,7 @@ mod tests {
113 use test_utils::mark; 113 use test_utils::mark;
114 114
115 use crate::{ 115 use crate::{
116 test_utils::{check_edit, check_edit_with_config}, 116 test_utils::{check_edit, check_edit_with_config, TEST_CONFIG},
117 CompletionConfig, 117 CompletionConfig,
118 }; 118 };
119 119
@@ -211,7 +211,7 @@ fn main() { S::foo(${1:&self})$0 }
211 fn suppress_arg_snippets() { 211 fn suppress_arg_snippets() {
212 mark::check!(suppress_arg_snippets); 212 mark::check!(suppress_arg_snippets);
213 check_edit_with_config( 213 check_edit_with_config(
214 CompletionConfig { add_call_argument_snippets: false, ..CompletionConfig::default() }, 214 CompletionConfig { add_call_argument_snippets: false, ..TEST_CONFIG },
215 "with_args", 215 "with_args",
216 r#" 216 r#"
217fn with_args(x: i32, y: String) {} 217fn with_args(x: i32, y: String) {}
diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs
index a3b6a3cac..61d8a17e5 100644
--- a/crates/completion/src/render/pattern.rs
+++ b/crates/completion/src/render/pattern.rs
@@ -1,12 +1,10 @@
1//! Renderer for patterns. 1//! Renderer for patterns.
2 2
3use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind}; 3use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind};
4use ide_db::helpers::SnippetCap;
4use itertools::Itertools; 5use itertools::Itertools;
5 6
6use crate::{ 7use crate::{item::CompletionKind, render::RenderContext, CompletionItem, CompletionItemKind};
7 config::SnippetCap, item::CompletionKind, render::RenderContext, CompletionItem,
8 CompletionItemKind,
9};
10 8
11fn visible_fields( 9fn visible_fields(
12 ctx: &RenderContext<'_>, 10 ctx: &RenderContext<'_>,
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index eb0c16f52..b5e296777 100644
--- a/crates/completion/src/test_utils.rs
+++ b/crates/completion/src/test_utils.rs
@@ -1,8 +1,11 @@
1//! Runs completion for testing purposes. 1//! Runs completion for testing purposes.
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::base_db::{fixture::ChangeFixture, FileLoader, FilePosition}; 4use ide_db::{
5use ide_db::RootDatabase; 5 base_db::{fixture::ChangeFixture, FileLoader, FilePosition},
6 helpers::{insert_use::MergeBehavior, SnippetCap},
7 RootDatabase,
8};
6use itertools::Itertools; 9use itertools::Itertools;
7use stdx::{format_to, trim_indent}; 10use stdx::{format_to, trim_indent};
8use syntax::{AstNode, NodeOrToken, SyntaxElement}; 11use syntax::{AstNode, NodeOrToken, SyntaxElement};
@@ -10,6 +13,15 @@ use test_utils::{assert_eq_text, RangeOrOffset};
10 13
11use crate::{item::CompletionKind, CompletionConfig, CompletionItem}; 14use crate::{item::CompletionKind, CompletionConfig, CompletionItem};
12 15
16pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
17 enable_postfix_completions: true,
18 enable_autoimport_completions: true,
19 add_call_parenthesis: true,
20 add_call_argument_snippets: true,
21 snippet_cap: SnippetCap::new(true),
22 merge: Some(MergeBehavior::Full),
23};
24
13/// Creates analysis from a multi-file fixture, returns positions marked with <|>. 25/// Creates analysis from a multi-file fixture, returns positions marked with <|>.
14pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) { 26pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
15 let change_fixture = ChangeFixture::parse(ra_fixture); 27 let change_fixture = ChangeFixture::parse(ra_fixture);
@@ -24,7 +36,7 @@ pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
24} 36}
25 37
26pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> { 38pub(crate) fn do_completion(code: &str, kind: CompletionKind) -> Vec<CompletionItem> {
27 do_completion_with_config(CompletionConfig::default(), code, kind) 39 do_completion_with_config(TEST_CONFIG, code, kind)
28} 40}
29 41
30pub(crate) fn do_completion_with_config( 42pub(crate) fn do_completion_with_config(
@@ -39,7 +51,7 @@ pub(crate) fn do_completion_with_config(
39} 51}
40 52
41pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String { 53pub(crate) fn completion_list(code: &str, kind: CompletionKind) -> String {
42 completion_list_with_config(CompletionConfig::default(), code, kind) 54 completion_list_with_config(TEST_CONFIG, code, kind)
43} 55}
44 56
45pub(crate) fn completion_list_with_config( 57pub(crate) fn completion_list_with_config(
@@ -76,7 +88,7 @@ fn monospace_width(s: &str) -> usize {
76} 88}
77 89
78pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) { 90pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
79 check_edit_with_config(CompletionConfig::default(), what, ra_fixture_before, ra_fixture_after) 91 check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after)
80} 92}
81 93
82pub(crate) fn check_edit_with_config( 94pub(crate) fn check_edit_with_config(
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 72c8bfd09..cea2a13c8 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -80,7 +80,7 @@ pub use crate::{
80 HighlightedRange, 80 HighlightedRange,
81 }, 81 },
82}; 82};
83pub use assists::{Assist, AssistConfig, AssistId, AssistKind}; 83pub use assists::{Assist, AssistConfig, AssistId, AssistKind, InsertUseConfig};
84pub use completion::{ 84pub use completion::{
85 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, 85 CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, ImportEdit,
86 InsertTextFormat, 86 InsertTextFormat,
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index d988588ff..e3e5670f1 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -1,9 +1,10 @@
1//! A module with ide helpers for high-level ide features. 1//! A module with ide helpers for high-level ide features.
2use crate::RootDatabase; 2pub mod insert_use;
3
3use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait}; 4use hir::{Crate, Enum, Module, ScopeDef, Semantics, Trait};
4use syntax::ast::{self, make}; 5use syntax::ast::{self, make};
5 6
6pub mod insert_use; 7use crate::RootDatabase;
7 8
8/// Converts the mod path struct into its ast representation. 9/// Converts the mod path struct into its ast representation.
9pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path { 10pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
@@ -201,3 +202,18 @@ pub use prelude::*;
201 Some(def) 202 Some(def)
202 } 203 }
203} 204}
205
206#[derive(Clone, Copy, Debug, PartialEq, Eq)]
207pub struct SnippetCap {
208 _private: (),
209}
210
211impl SnippetCap {
212 pub const fn new(allow_snippets: bool) -> Option<SnippetCap> {
213 if allow_snippets {
214 Some(SnippetCap { _private: () })
215 } else {
216 None
217 }
218 }
219}
diff --git a/crates/rust-analyzer/src/cli/analysis_bench.rs b/crates/rust-analyzer/src/cli/analysis_bench.rs
index 5a8484c62..7d3fda7a8 100644
--- a/crates/rust-analyzer/src/cli/analysis_bench.rs
+++ b/crates/rust-analyzer/src/cli/analysis_bench.rs
@@ -6,9 +6,12 @@ use anyhow::{bail, format_err, Result};
6use ide::{ 6use ide::{
7 Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol, 7 Analysis, AnalysisHost, Change, CompletionConfig, DiagnosticsConfig, FilePosition, LineCol,
8}; 8};
9use ide_db::base_db::{ 9use ide_db::{
10 salsa::{Database, Durability}, 10 base_db::{
11 FileId, 11 salsa::{Database, Durability},
12 FileId,
13 },
14 helpers::SnippetCap,
12}; 15};
13use vfs::AbsPathBuf; 16use vfs::AbsPathBuf;
14 17
@@ -87,7 +90,14 @@ impl BenchCmd {
87 let file_position = FilePosition { file_id, offset }; 90 let file_position = FilePosition { file_id, offset };
88 91
89 if is_completion { 92 if is_completion {
90 let options = CompletionConfig::default(); 93 let options = CompletionConfig {
94 enable_postfix_completions: true,
95 enable_autoimport_completions: true,
96 add_call_parenthesis: true,
97 add_call_argument_snippets: true,
98 snippet_cap: SnippetCap::new(true),
99 merge: None,
100 };
91 let res = do_work(&mut host, file_id, |analysis| { 101 let res = do_work(&mut host, file_id, |analysis| {
92 analysis.completions(&options, file_position) 102 analysis.completions(&options, file_position)
93 }); 103 });
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index ce9526315..e3ba81ac6 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -11,8 +11,11 @@ use std::{convert::TryFrom, ffi::OsString, path::PathBuf};
11 11
12use flycheck::FlycheckConfig; 12use flycheck::FlycheckConfig;
13use hir::PrefixKind; 13use hir::PrefixKind;
14use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig}; 14use ide::{
15use ide_db::helpers::insert_use::MergeBehavior; 15 AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig,
16 InsertUseConfig,
17};
18use ide_db::helpers::{insert_use::MergeBehavior, SnippetCap};
16use itertools::Itertools; 19use itertools::Itertools;
17use lsp_types::{ClientCapabilities, MarkupKind}; 20use lsp_types::{ClientCapabilities, MarkupKind};
18use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest}; 21use project_model::{CargoConfig, ProjectJson, ProjectJsonData, ProjectManifest};
@@ -534,37 +537,39 @@ impl Config {
534 } 537 }
535 } 538 }
536 pub fn completion(&self) -> CompletionConfig { 539 pub fn completion(&self) -> CompletionConfig {
537 let mut res = CompletionConfig::default(); 540 CompletionConfig {
538 res.enable_postfix_completions = self.data.completion_postfix_enable; 541 enable_postfix_completions: self.data.completion_postfix_enable,
539 res.enable_autoimport_completions = 542 enable_autoimport_completions: self.data.completion_autoimport_enable
540 self.data.completion_autoimport_enable && completion_item_edit_resolve(&self.caps); 543 && completion_item_edit_resolve(&self.caps),
541 res.add_call_parenthesis = self.data.completion_addCallParenthesis; 544 add_call_parenthesis: self.data.completion_addCallParenthesis,
542 res.add_call_argument_snippets = self.data.completion_addCallArgumentSnippets; 545 add_call_argument_snippets: self.data.completion_addCallArgumentSnippets,
543 res.merge = self.merge_behavior(); 546 merge: self.merge_behavior(),
544 547 snippet_cap: SnippetCap::new(try_or!(
545 res.allow_snippets(try_or!( 548 self.caps
546 self.caps 549 .text_document
547 .text_document 550 .as_ref()?
548 .as_ref()? 551 .completion
549 .completion 552 .as_ref()?
550 .as_ref()? 553 .completion_item
551 .completion_item 554 .as_ref()?
552 .as_ref()? 555 .snippet_support?,
553 .snippet_support?, 556 false
554 false 557 )),
555 )); 558 }
556 res
557 } 559 }
558 pub fn assist(&self) -> AssistConfig { 560 pub fn assist(&self) -> AssistConfig {
559 let mut res = AssistConfig::default(); 561 AssistConfig {
560 res.insert_use.merge = self.merge_behavior(); 562 snippet_cap: SnippetCap::new(self.experimental("snippetTextEdit")),
561 res.insert_use.prefix_kind = match self.data.assist_importPrefix { 563 allowed: None,
562 ImportPrefixDef::Plain => PrefixKind::Plain, 564 insert_use: InsertUseConfig {
563 ImportPrefixDef::ByCrate => PrefixKind::ByCrate, 565 merge: self.merge_behavior(),
564 ImportPrefixDef::BySelf => PrefixKind::BySelf, 566 prefix_kind: match self.data.assist_importPrefix {
565 }; 567 ImportPrefixDef::Plain => PrefixKind::Plain,
566 res.allow_snippets(self.experimental("snippetTextEdit")); 568 ImportPrefixDef::ByCrate => PrefixKind::ByCrate,
567 res 569 ImportPrefixDef::BySelf => PrefixKind::BySelf,
570 },
571 },
572 }
568 } 573 }
569 pub fn call_info_full(&self) -> bool { 574 pub fn call_info_full(&self) -> bool {
570 self.data.callInfo_full 575 self.data.callInfo_full
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index a5f7e3af7..bb221c1d1 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -850,6 +850,7 @@ pub(crate) fn markup_content(markup: Markup) -> lsp_types::MarkupContent {
850#[cfg(test)] 850#[cfg(test)]
851mod tests { 851mod tests {
852 use ide::Analysis; 852 use ide::Analysis;
853 use ide_db::helpers::SnippetCap;
853 854
854 use super::*; 855 use super::*;
855 856
@@ -868,7 +869,14 @@ mod tests {
868 let (analysis, file_id) = Analysis::from_single_file(text); 869 let (analysis, file_id) = Analysis::from_single_file(text);
869 let completions: Vec<(String, Option<String>)> = analysis 870 let completions: Vec<(String, Option<String>)> = analysis
870 .completions( 871 .completions(
871 &ide::CompletionConfig::default(), 872 &ide::CompletionConfig {
873 enable_postfix_completions: true,
874 enable_autoimport_completions: true,
875 add_call_parenthesis: true,
876 add_call_argument_snippets: true,
877 snippet_cap: SnippetCap::new(true),
878 merge: None,
879 },
872 ide_db::base_db::FilePosition { file_id, offset }, 880 ide_db::base_db::FilePosition { file_id, offset },
873 ) 881 )
874 .unwrap() 882 .unwrap()