aboutsummaryrefslogtreecommitdiff
path: root/crates/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion')
-rw-r--r--crates/completion/Cargo.toml4
-rw-r--r--crates/completion/src/completions.rs5
-rw-r--r--crates/completion/src/completions/attribute.rs73
-rw-r--r--crates/completion/src/completions/dot.rs48
-rw-r--r--crates/completion/src/completions/fn_param.rs8
-rw-r--r--crates/completion/src/completions/keyword.rs56
-rw-r--r--crates/completion/src/completions/macro_in_item_position.rs2
-rw-r--r--crates/completion/src/completions/mod_.rs87
-rw-r--r--crates/completion/src/completions/pattern.rs20
-rw-r--r--crates/completion/src/completions/postfix.rs79
-rw-r--r--crates/completion/src/completions/postfix/format_like.rs7
-rw-r--r--crates/completion/src/completions/qualified_path.rs70
-rw-r--r--crates/completion/src/completions/record.rs94
-rw-r--r--crates/completion/src/completions/snippet.rs14
-rw-r--r--crates/completion/src/completions/trait_impl.rs123
-rw-r--r--crates/completion/src/completions/unqualified_path.rs109
-rw-r--r--crates/completion/src/config.rs48
-rw-r--r--crates/completion/src/context.rs10
-rw-r--r--crates/completion/src/item.rs6
-rw-r--r--crates/completion/src/lib.rs23
-rw-r--r--crates/completion/src/patterns.rs56
-rw-r--r--crates/completion/src/render.rs61
-rw-r--r--crates/completion/src/render/const_.rs8
-rw-r--r--crates/completion/src/render/enum_variant.rs2
-rw-r--r--crates/completion/src/render/function.rs36
-rw-r--r--crates/completion/src/render/macro_.rs23
-rw-r--r--crates/completion/src/render/pattern.rs6
-rw-r--r--crates/completion/src/render/type_alias.rs8
-rw-r--r--crates/completion/src/test_utils.rs26
29 files changed, 564 insertions, 548 deletions
diff --git a/crates/completion/Cargo.toml b/crates/completion/Cargo.toml
index 35e169a28..99a1bdd54 100644
--- a/crates/completion/Cargo.toml
+++ b/crates/completion/Cargo.toml
@@ -10,7 +10,7 @@ edition = "2018"
10doctest = false 10doctest = false
11 11
12[dependencies] 12[dependencies]
13itertools = "0.9.0" 13itertools = "0.10.0"
14log = "0.4.8" 14log = "0.4.8"
15rustc-hash = "1.1.0" 15rustc-hash = "1.1.0"
16either = "1.6.1" 16either = "1.6.1"
@@ -28,4 +28,4 @@ test_utils = { path = "../test_utils", version = "0.0.0" }
28hir = { path = "../hir", version = "0.0.0" } 28hir = { path = "../hir", version = "0.0.0" }
29 29
30[dev-dependencies] 30[dev-dependencies]
31expect-test = "1.0" 31expect-test = "1.1"
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs
index d9fe13485..00c9e76f0 100644
--- a/crates/completion/src/completions.rs
+++ b/crates/completion/src/completions.rs
@@ -106,8 +106,9 @@ impl Completions {
106 func: hir::Function, 106 func: hir::Function,
107 local_name: Option<String>, 107 local_name: Option<String>,
108 ) { 108 ) {
109 let item = render_fn(RenderContext::new(ctx), None, local_name, func); 109 if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) {
110 self.add(item) 110 self.add(item)
111 }
111 } 112 }
112 113
113 pub(crate) fn add_variant_pat( 114 pub(crate) fn add_variant_pat(
diff --git a/crates/completion/src/completions/attribute.rs b/crates/completion/src/completions/attribute.rs
index 19ce2482f..e5522980d 100644
--- a/crates/completion/src/completions/attribute.rs
+++ b/crates/completion/src/completions/attribute.rs
@@ -5,7 +5,7 @@
5 5
6use itertools::Itertools; 6use itertools::Itertools;
7use rustc_hash::FxHashSet; 7use rustc_hash::FxHashSet;
8use syntax::{ast, AstNode, SyntaxKind}; 8use syntax::{ast, AstNode, T};
9 9
10use crate::{ 10use crate::{
11 context::CompletionContext, 11 context::CompletionContext,
@@ -21,19 +21,16 @@ pub(crate) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext)
21 21
22 let attribute = ctx.attribute_under_caret.as_ref()?; 22 let attribute = ctx.attribute_under_caret.as_ref()?;
23 match (attribute.path(), attribute.token_tree()) { 23 match (attribute.path(), attribute.token_tree()) {
24 (Some(path), Some(token_tree)) if path.to_string() == "derive" => { 24 (Some(path), Some(token_tree)) => {
25 complete_derive(acc, ctx, token_tree) 25 let path = path.syntax().text();
26 } 26 if path == "derive" {
27 (Some(path), Some(token_tree)) if path.to_string() == "feature" => { 27 complete_derive(acc, ctx, token_tree)
28 complete_lint(acc, ctx, token_tree, FEATURES); 28 } else if path == "feature" {
29 } 29 complete_lint(acc, ctx, token_tree, FEATURES)
30 (Some(path), Some(token_tree)) 30 } else if path == "allow" || path == "warn" || path == "deny" || path == "forbid" {
31 if ["allow", "warn", "deny", "forbid"] 31 complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINT_COMPLETIONS);
32 .iter() 32 complete_lint(acc, ctx, token_tree, CLIPPY_LINTS);
33 .any(|lint_level| lint_level == &path.to_string()) => 33 }
34 {
35 complete_lint(acc, ctx, token_tree.clone(), DEFAULT_LINT_COMPLETIONS);
36 complete_lint(acc, ctx, token_tree, CLIPPY_LINTS);
37 } 34 }
38 (_, Some(_token_tree)) => {} 35 (_, Some(_token_tree)) => {}
39 _ => complete_attribute_start(acc, ctx, attribute), 36 _ => complete_attribute_start(acc, ctx, attribute),
@@ -54,11 +51,8 @@ fn complete_attribute_start(acc: &mut Completions, ctx: &CompletionContext, attr
54 item = item.lookup_by(lookup); 51 item = item.lookup_by(lookup);
55 } 52 }
56 53
57 match (attr_completion.snippet, ctx.config.snippet_cap) { 54 if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) {
58 (Some(snippet), Some(cap)) => { 55 item = item.insert_snippet(cap, snippet);
59 item = item.insert_snippet(cap, snippet);
60 }
61 _ => {}
62 } 56 }
63 57
64 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner { 58 if attribute.kind() == ast::AttrKind::Inner || !attr_completion.prefer_inner {
@@ -98,7 +92,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[
98 attr(r#"crate_name = """#, Some("crate_name"), Some(r#"crate_name = "${0:crate_name}""#)) 92 attr(r#"crate_name = """#, Some("crate_name"), Some(r#"crate_name = "${0:crate_name}""#))
99 .prefer_inner(), 93 .prefer_inner(),
100 attr("deny(…)", Some("deny"), Some("deny(${0:lint})")), 94 attr("deny(…)", Some("deny"), Some("deny(${0:lint})")),
101 attr(r#"deprecated = "…""#, Some("deprecated"), Some(r#"deprecated = "${0:reason}""#)), 95 attr(r#"deprecated"#, Some("deprecated"), Some(r#"deprecated"#)),
102 attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)), 96 attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)),
103 attr( 97 attr(
104 r#"export_name = "…""#, 98 r#"export_name = "…""#,
@@ -121,7 +115,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[
121 ), 115 ),
122 attr("macro_export", None, None), 116 attr("macro_export", None, None),
123 attr("macro_use", None, None), 117 attr("macro_use", None, None),
124 attr(r#"must_use = "…""#, Some("must_use"), Some(r#"must_use = "${0:reason}""#)), 118 attr(r#"must_use"#, Some("must_use"), Some(r#"must_use"#)),
125 attr("no_link", None, None).prefer_inner(), 119 attr("no_link", None, None).prefer_inner(),
126 attr("no_implicit_prelude", None, None).prefer_inner(), 120 attr("no_implicit_prelude", None, None).prefer_inner(),
127 attr("no_main", None, None).prefer_inner(), 121 attr("no_main", None, None).prefer_inner(),
@@ -136,11 +130,7 @@ const ATTRIBUTES: &[AttrCompletion] = &[
136 attr("recursion_limit = …", Some("recursion_limit"), Some("recursion_limit = ${0:128}")) 130 attr("recursion_limit = …", Some("recursion_limit"), Some("recursion_limit = ${0:128}"))
137 .prefer_inner(), 131 .prefer_inner(),
138 attr("repr(…)", Some("repr"), Some("repr(${0:C})")), 132 attr("repr(…)", Some("repr"), Some("repr(${0:C})")),
139 attr( 133 attr("should_panic", Some("should_panic"), Some(r#"should_panic"#)),
140 "should_panic(…)",
141 Some("should_panic"),
142 Some(r#"should_panic(expected = "${0:reason}")"#),
143 ),
144 attr( 134 attr(
145 r#"target_feature = "…""#, 135 r#"target_feature = "…""#,
146 Some("target_feature"), 136 Some("target_feature"),
@@ -215,8 +205,7 @@ fn complete_lint(
215fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> { 205fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>, ()> {
216 match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) { 206 match (derive_input.left_delimiter_token(), derive_input.right_delimiter_token()) {
217 (Some(left_paren), Some(right_paren)) 207 (Some(left_paren), Some(right_paren))
218 if left_paren.kind() == SyntaxKind::L_PAREN 208 if left_paren.kind() == T!['('] && right_paren.kind() == T![')'] =>
219 && right_paren.kind() == SyntaxKind::R_PAREN =>
220 { 209 {
221 let mut input_derives = FxHashSet::default(); 210 let mut input_derives = FxHashSet::default();
222 let mut current_derive = String::new(); 211 let mut current_derive = String::new();
@@ -228,13 +217,13 @@ fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<Strin
228 .skip(1) 217 .skip(1)
229 .take_while(|token| token != &right_paren) 218 .take_while(|token| token != &right_paren)
230 { 219 {
231 if SyntaxKind::COMMA == token.kind() { 220 if T![,] == token.kind() {
232 if !current_derive.is_empty() { 221 if !current_derive.is_empty() {
233 input_derives.insert(current_derive); 222 input_derives.insert(current_derive);
234 current_derive = String::new(); 223 current_derive = String::new();
235 } 224 }
236 } else { 225 } else {
237 current_derive.push_str(token.to_string().trim()); 226 current_derive.push_str(token.text().trim());
238 } 227 }
239 } 228 }
240 229
@@ -417,7 +406,7 @@ mod tests {
417 fn empty_derive_completion() { 406 fn empty_derive_completion() {
418 check( 407 check(
419 r#" 408 r#"
420#[derive(<|>)] 409#[derive($0)]
421struct Test {} 410struct Test {}
422 "#, 411 "#,
423 expect![[r#" 412 expect![[r#"
@@ -438,7 +427,7 @@ struct Test {}
438 fn no_completion_for_incorrect_derive() { 427 fn no_completion_for_incorrect_derive() {
439 check( 428 check(
440 r#" 429 r#"
441#[derive{<|>)] 430#[derive{$0)]
442struct Test {} 431struct Test {}
443"#, 432"#,
444 expect![[r#""#]], 433 expect![[r#""#]],
@@ -449,7 +438,7 @@ struct Test {}
449 fn derive_with_input_completion() { 438 fn derive_with_input_completion() {
450 check( 439 check(
451 r#" 440 r#"
452#[derive(serde::Serialize, PartialEq, <|>)] 441#[derive(serde::Serialize, PartialEq, $0)]
453struct Test {} 442struct Test {}
454"#, 443"#,
455 expect![[r#" 444 expect![[r#"
@@ -468,7 +457,7 @@ struct Test {}
468 #[test] 457 #[test]
469 fn test_attribute_completion() { 458 fn test_attribute_completion() {
470 check( 459 check(
471 r#"#[<|>]"#, 460 r#"#[$0]"#,
472 expect![[r#" 461 expect![[r#"
473 at allow(…) 462 at allow(…)
474 at automatically_derived 463 at automatically_derived
@@ -476,7 +465,7 @@ struct Test {}
476 at cfg(…) 465 at cfg(…)
477 at cold 466 at cold
478 at deny(…) 467 at deny(…)
479 at deprecated = "…" 468 at deprecated
480 at derive(…) 469 at derive(…)
481 at export_name = "…" 470 at export_name = "…"
482 at doc = "…" 471 at doc = "…"
@@ -488,7 +477,7 @@ struct Test {}
488 at link_section = "…" 477 at link_section = "…"
489 at macro_export 478 at macro_export
490 at macro_use 479 at macro_use
491 at must_use = "…" 480 at must_use
492 at no_mangle 481 at no_mangle
493 at non_exhaustive 482 at non_exhaustive
494 at path = "…" 483 at path = "…"
@@ -496,7 +485,7 @@ struct Test {}
496 at proc_macro_attribute 485 at proc_macro_attribute
497 at proc_macro_derive(…) 486 at proc_macro_derive(…)
498 at repr(…) 487 at repr(…)
499 at should_panic(…) 488 at should_panic
500 at target_feature = "…" 489 at target_feature = "…"
501 at test 490 at test
502 at track_caller 491 at track_caller
@@ -508,13 +497,13 @@ struct Test {}
508 497
509 #[test] 498 #[test]
510 fn test_attribute_completion_inside_nested_attr() { 499 fn test_attribute_completion_inside_nested_attr() {
511 check(r#"#[cfg(<|>)]"#, expect![[]]) 500 check(r#"#[cfg($0)]"#, expect![[]])
512 } 501 }
513 502
514 #[test] 503 #[test]
515 fn test_inner_attribute_completion() { 504 fn test_inner_attribute_completion() {
516 check( 505 check(
517 r"#![<|>]", 506 r"#![$0]",
518 expect![[r#" 507 expect![[r#"
519 at allow(…) 508 at allow(…)
520 at automatically_derived 509 at automatically_derived
@@ -523,7 +512,7 @@ struct Test {}
523 at cold 512 at cold
524 at crate_name = "" 513 at crate_name = ""
525 at deny(…) 514 at deny(…)
526 at deprecated = "…" 515 at deprecated
527 at derive(…) 516 at derive(…)
528 at export_name = "…" 517 at export_name = "…"
529 at doc = "…" 518 at doc = "…"
@@ -537,7 +526,7 @@ struct Test {}
537 at link_section = "…" 526 at link_section = "…"
538 at macro_export 527 at macro_export
539 at macro_use 528 at macro_use
540 at must_use = "…" 529 at must_use
541 at no_link 530 at no_link
542 at no_implicit_prelude 531 at no_implicit_prelude
543 at no_main 532 at no_main
@@ -551,7 +540,7 @@ struct Test {}
551 at proc_macro_derive(…) 540 at proc_macro_derive(…)
552 at recursion_limit = … 541 at recursion_limit = …
553 at repr(…) 542 at repr(…)
554 at should_panic(…) 543 at should_panic
555 at target_feature = "…" 544 at target_feature = "…"
556 at test 545 at test
557 at track_caller 546 at track_caller
diff --git a/crates/completion/src/completions/dot.rs b/crates/completion/src/completions/dot.rs
index 551ef1771..d04eef65a 100644
--- a/crates/completion/src/completions/dot.rs
+++ b/crates/completion/src/completions/dot.rs
@@ -79,7 +79,7 @@ struct S { foo: u32 }
79impl S { 79impl S {
80 fn bar(&self) {} 80 fn bar(&self) {}
81} 81}
82fn foo(s: S) { s.<|> } 82fn foo(s: S) { s.$0 }
83"#, 83"#,
84 expect![[r#" 84 expect![[r#"
85 fd foo u32 85 fd foo u32
@@ -94,7 +94,7 @@ fn foo(s: S) { s.<|> }
94 r#" 94 r#"
95struct S { the_field: (u32,) } 95struct S { the_field: (u32,) }
96impl S { 96impl S {
97 fn foo(self) { self.<|> } 97 fn foo(self) { self.$0 }
98} 98}
99"#, 99"#,
100 expect![[r#" 100 expect![[r#"
@@ -110,7 +110,7 @@ impl S {
110 r#" 110 r#"
111struct A { the_field: (u32, i32) } 111struct A { the_field: (u32, i32) }
112impl A { 112impl A {
113 fn foo(&self) { self.<|> } 113 fn foo(&self) { self.$0 }
114} 114}
115"#, 115"#,
116 expect![[r#" 116 expect![[r#"
@@ -126,7 +126,7 @@ impl A {
126 check( 126 check(
127 r#" 127 r#"
128struct A { the_field: u32 } 128struct A { the_field: u32 }
129fn foo(a: A) { a.<|>() } 129fn foo(a: A) { a.$0() }
130"#, 130"#,
131 expect![[""]], 131 expect![[""]],
132 ); 132 );
@@ -144,7 +144,7 @@ mod inner {
144 pub(crate) super_field: u32, 144 pub(crate) super_field: u32,
145 } 145 }
146} 146}
147fn foo(a: inner::A) { a.<|> } 147fn foo(a: inner::A) { a.$0 }
148"#, 148"#,
149 expect![[r#" 149 expect![[r#"
150 fd pub_field u32 150 fd pub_field u32
@@ -162,7 +162,7 @@ mod m {
162 pub(crate) fn the_method(&self) {} 162 pub(crate) fn the_method(&self) {}
163 } 163 }
164} 164}
165fn foo(a: A) { a.<|> } 165fn foo(a: A) { a.$0 }
166"#, 166"#,
167 expect![[r#" 167 expect![[r#"
168 me the_method() pub(crate) fn the_method(&self) 168 me the_method() pub(crate) fn the_method(&self)
@@ -175,7 +175,7 @@ fn foo(a: A) { a.<|> }
175 check( 175 check(
176 r#" 176 r#"
177union U { field: u8, other: u16 } 177union U { field: u8, other: u16 }
178fn foo(u: U) { u.<|> } 178fn foo(u: U) { u.$0 }
179"#, 179"#,
180 expect![[r#" 180 expect![[r#"
181 fd field u8 181 fd field u8
@@ -195,7 +195,7 @@ impl A<u32> {
195impl A<i32> { 195impl A<i32> {
196 fn the_other_method(&self) {} 196 fn the_other_method(&self) {}
197} 197}
198fn foo(a: A<u32>) { a.<|> } 198fn foo(a: A<u32>) { a.$0 }
199"#, 199"#,
200 expect![[r#" 200 expect![[r#"
201 me the_method() fn the_method(&self) 201 me the_method() fn the_method(&self)
@@ -210,7 +210,7 @@ fn foo(a: A<u32>) { a.<|> }
210struct A {} 210struct A {}
211trait Trait { fn the_method(&self); } 211trait Trait { fn the_method(&self); }
212impl Trait for A {} 212impl Trait for A {}
213fn foo(a: A) { a.<|> } 213fn foo(a: A) { a.$0 }
214"#, 214"#,
215 expect![[r#" 215 expect![[r#"
216 me the_method() fn the_method(&self) 216 me the_method() fn the_method(&self)
@@ -225,7 +225,7 @@ fn foo(a: A) { a.<|> }
225struct A {} 225struct A {}
226trait Trait { fn the_method(&self); } 226trait Trait { fn the_method(&self); }
227impl<T> Trait for T {} 227impl<T> Trait for T {}
228fn foo(a: &A) { a.<|> } 228fn foo(a: &A) { a.$0 }
229", 229",
230 expect![[r#" 230 expect![[r#"
231 me the_method() fn the_method(&self) 231 me the_method() fn the_method(&self)
@@ -243,7 +243,7 @@ mod m {
243} 243}
244use m::Trait; 244use m::Trait;
245impl Trait for A {} 245impl Trait for A {}
246fn foo(a: A) { a.<|> } 246fn foo(a: A) { a.$0 }
247", 247",
248 expect![[r#" 248 expect![[r#"
249 me the_method() fn the_method(&self) 249 me the_method() fn the_method(&self)
@@ -260,7 +260,7 @@ impl A {
260 fn the_method() {} 260 fn the_method() {}
261} 261}
262fn foo(a: A) { 262fn foo(a: A) {
263 a.<|> 263 a.$0
264} 264}
265"#, 265"#,
266 expect![[""]], 266 expect![[""]],
@@ -273,7 +273,7 @@ fn foo(a: A) {
273 r#" 273 r#"
274fn foo() { 274fn foo() {
275 let b = (0, 3.14); 275 let b = (0, 3.14);
276 b.<|> 276 b.$0
277} 277}
278"#, 278"#,
279 expect![[r#" 279 expect![[r#"
@@ -295,7 +295,7 @@ struct T(S);
295impl T { 295impl T {
296 fn foo(&self) { 296 fn foo(&self) {
297 // FIXME: This doesn't work without the trailing `a` as `0.` is a float 297 // FIXME: This doesn't work without the trailing `a` as `0.` is a float
298 self.0.a<|> 298 self.0.a$0
299 } 299 }
300} 300}
301"#, 301"#,
@@ -311,7 +311,7 @@ impl T {
311 r#" 311 r#"
312struct A { the_field: u32 } 312struct A { the_field: u32 }
313const X: u32 = { 313const X: u32 = {
314 A { the_field: 92 }.<|> 314 A { the_field: 92 }.$0
315}; 315};
316"#, 316"#,
317 expect![[r#" 317 expect![[r#"
@@ -327,7 +327,7 @@ const X: u32 = {
327macro_rules! m { ($e:expr) => { $e } } 327macro_rules! m { ($e:expr) => { $e } }
328struct A { the_field: u32 } 328struct A { the_field: u32 }
329fn foo(a: A) { 329fn foo(a: A) {
330 m!(a.x<|>) 330 m!(a.x$0)
331} 331}
332"#, 332"#,
333 expect![[r#" 333 expect![[r#"
@@ -344,7 +344,7 @@ fn foo(a: A) {
344macro_rules! m { ($e:expr) => { $e } } 344macro_rules! m { ($e:expr) => { $e } }
345struct A { the_field: u32 } 345struct A { the_field: u32 }
346fn foo(a: A) { 346fn foo(a: A) {
347 m!(a.<|>) 347 m!(a.$0)
348} 348}
349"#, 349"#,
350 expect![[r#" 350 expect![[r#"
@@ -360,7 +360,7 @@ fn foo(a: A) {
360macro_rules! m { ($e:expr) => { $e } } 360macro_rules! m { ($e:expr) => { $e } }
361struct A { the_field: u32 } 361struct A { the_field: u32 }
362fn foo(a: A) { 362fn foo(a: A) {
363 m!(m!(m!(a.x<|>))) 363 m!(m!(m!(a.x$0)))
364} 364}
365"#, 365"#,
366 expect![[r#" 366 expect![[r#"
@@ -373,20 +373,20 @@ fn foo(a: A) {
373 fn macro_expansion_resilient() { 373 fn macro_expansion_resilient() {
374 check( 374 check(
375 r#" 375 r#"
376macro_rules! dbg { 376macro_rules! d {
377 () => {}; 377 () => {};
378 ($val:expr) => { 378 ($val:expr) => {
379 match $val { tmp => { tmp } } 379 match $val { tmp => { tmp } }
380 }; 380 };
381 // Trailing comma with single argument is ignored 381 // Trailing comma with single argument is ignored
382 ($val:expr,) => { $crate::dbg!($val) }; 382 ($val:expr,) => { $crate::d!($val) };
383 ($($val:expr),+ $(,)?) => { 383 ($($val:expr),+ $(,)?) => {
384 ($($crate::dbg!($val)),+,) 384 ($($crate::d!($val)),+,)
385 }; 385 };
386} 386}
387struct A { the_field: u32 } 387struct A { the_field: u32 }
388fn foo(a: A) { 388fn foo(a: A) {
389 dbg!(a.<|>) 389 d!(a.$0)
390} 390}
391"#, 391"#,
392 expect![[r#" 392 expect![[r#"
@@ -405,7 +405,7 @@ impl<T> HashSet<T> {
405} 405}
406fn foo() { 406fn foo() {
407 let s: HashSet<_>; 407 let s: HashSet<_>;
408 s.<|> 408 s.$0
409} 409}
410"#, 410"#,
411 expect![[r#" 411 expect![[r#"
@@ -421,7 +421,7 @@ fn foo() {
421struct S; 421struct S;
422impl S { fn foo(&self) {} } 422impl S { fn foo(&self) {} }
423macro_rules! make_s { () => { S }; } 423macro_rules! make_s { () => { S }; }
424fn main() { make_s!().f<|>; } 424fn main() { make_s!().f$0; }
425"#, 425"#,
426 expect![[r#" 426 expect![[r#"
427 me foo() fn foo(&self) 427 me foo() fn foo(&self)
diff --git a/crates/completion/src/completions/fn_param.rs b/crates/completion/src/completions/fn_param.rs
index e777a53c1..5505c3559 100644
--- a/crates/completion/src/completions/fn_param.rs
+++ b/crates/completion/src/completions/fn_param.rs
@@ -81,7 +81,7 @@ mod tests {
81 r#" 81 r#"
82fn foo(file_id: FileId) {} 82fn foo(file_id: FileId) {}
83fn bar(file_id: FileId) {} 83fn bar(file_id: FileId) {}
84fn baz(file<|>) {} 84fn baz(file$0) {}
85"#, 85"#,
86 expect![[r#" 86 expect![[r#"
87 bn file_id: FileId 87 bn file_id: FileId
@@ -94,7 +94,7 @@ fn baz(file<|>) {}
94 check( 94 check(
95 r#" 95 r#"
96fn foo(file_id: FileId) {} 96fn foo(file_id: FileId) {}
97fn baz(file<|>, x: i32) {} 97fn baz(file$0, x: i32) {}
98"#, 98"#,
99 expect![[r#" 99 expect![[r#"
100 bn file_id: FileId 100 bn file_id: FileId
@@ -110,7 +110,7 @@ pub(crate) trait SourceRoot {
110 pub fn contains(&self, file_id: FileId) -> bool; 110 pub fn contains(&self, file_id: FileId) -> bool;
111 pub fn module_map(&self) -> &ModuleMap; 111 pub fn module_map(&self) -> &ModuleMap;
112 pub fn lines(&self, file_id: FileId) -> &LineIndex; 112 pub fn lines(&self, file_id: FileId) -> &LineIndex;
113 pub fn syntax(&self, file<|>) 113 pub fn syntax(&self, file$0)
114} 114}
115"#, 115"#,
116 expect![[r#" 116 expect![[r#"
@@ -124,7 +124,7 @@ pub(crate) trait SourceRoot {
124 check( 124 check(
125 r#" 125 r#"
126fn outer(text: String) { 126fn outer(text: String) {
127 fn inner(<|>) 127 fn inner($0)
128} 128}
129"#, 129"#,
130 expect![[r#" 130 expect![[r#"
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs
index 1859dec70..425a688ff 100644
--- a/crates/completion/src/completions/keyword.rs
+++ b/crates/completion/src/completions/keyword.rs
@@ -193,7 +193,7 @@ mod tests {
193 #[test] 193 #[test]
194 fn test_keywords_in_use_stmt() { 194 fn test_keywords_in_use_stmt() {
195 check( 195 check(
196 r"use <|>", 196 r"use $0",
197 expect![[r#" 197 expect![[r#"
198 kw crate:: 198 kw crate::
199 kw self 199 kw self
@@ -202,7 +202,7 @@ mod tests {
202 ); 202 );
203 203
204 check( 204 check(
205 r"use a::<|>", 205 r"use a::$0",
206 expect![[r#" 206 expect![[r#"
207 kw self 207 kw self
208 kw super:: 208 kw super::
@@ -210,7 +210,7 @@ mod tests {
210 ); 210 );
211 211
212 check( 212 check(
213 r"use a::{b, <|>}", 213 r"use a::{b, $0}",
214 expect![[r#" 214 expect![[r#"
215 kw self 215 kw self
216 kw super:: 216 kw super::
@@ -221,7 +221,7 @@ mod tests {
221 #[test] 221 #[test]
222 fn test_keywords_at_source_file_level() { 222 fn test_keywords_at_source_file_level() {
223 check( 223 check(
224 r"m<|>", 224 r"m$0",
225 expect![[r#" 225 expect![[r#"
226 kw fn 226 kw fn
227 kw use 227 kw use
@@ -245,7 +245,7 @@ mod tests {
245 #[test] 245 #[test]
246 fn test_keywords_in_function() { 246 fn test_keywords_in_function() {
247 check( 247 check(
248 r"fn quux() { <|> }", 248 r"fn quux() { $0 }",
249 expect![[r#" 249 expect![[r#"
250 kw fn 250 kw fn
251 kw use 251 kw use
@@ -271,7 +271,7 @@ mod tests {
271 #[test] 271 #[test]
272 fn test_keywords_inside_block() { 272 fn test_keywords_inside_block() {
273 check( 273 check(
274 r"fn quux() { if true { <|> } }", 274 r"fn quux() { if true { $0 } }",
275 expect![[r#" 275 expect![[r#"
276 kw fn 276 kw fn
277 kw use 277 kw use
@@ -297,7 +297,7 @@ mod tests {
297 #[test] 297 #[test]
298 fn test_keywords_after_if() { 298 fn test_keywords_after_if() {
299 check( 299 check(
300 r#"fn quux() { if true { () } <|> }"#, 300 r#"fn quux() { if true { () } $0 }"#,
301 expect![[r#" 301 expect![[r#"
302 kw fn 302 kw fn
303 kw use 303 kw use
@@ -322,7 +322,7 @@ mod tests {
322 ); 322 );
323 check_edit( 323 check_edit(
324 "else", 324 "else",
325 r#"fn quux() { if true { () } <|> }"#, 325 r#"fn quux() { if true { () } $0 }"#,
326 r#"fn quux() { if true { () } else {$0} }"#, 326 r#"fn quux() { if true { () } else {$0} }"#,
327 ); 327 );
328 } 328 }
@@ -332,7 +332,7 @@ mod tests {
332 check( 332 check(
333 r#" 333 r#"
334fn quux() -> i32 { 334fn quux() -> i32 {
335 match () { () => <|> } 335 match () { () => $0 }
336} 336}
337"#, 337"#,
338 expect![[r#" 338 expect![[r#"
@@ -350,7 +350,7 @@ fn quux() -> i32 {
350 #[test] 350 #[test]
351 fn test_keywords_in_trait_def() { 351 fn test_keywords_in_trait_def() {
352 check( 352 check(
353 r"trait My { <|> }", 353 r"trait My { $0 }",
354 expect![[r#" 354 expect![[r#"
355 kw fn 355 kw fn
356 kw const 356 kw const
@@ -363,7 +363,7 @@ fn quux() -> i32 {
363 #[test] 363 #[test]
364 fn test_keywords_in_impl_def() { 364 fn test_keywords_in_impl_def() {
365 check( 365 check(
366 r"impl My { <|> }", 366 r"impl My { $0 }",
367 expect![[r#" 367 expect![[r#"
368 kw fn 368 kw fn
369 kw const 369 kw const
@@ -378,7 +378,7 @@ fn quux() -> i32 {
378 #[test] 378 #[test]
379 fn test_keywords_in_loop() { 379 fn test_keywords_in_loop() {
380 check( 380 check(
381 r"fn my() { loop { <|> } }", 381 r"fn my() { loop { $0 } }",
382 expect![[r#" 382 expect![[r#"
383 kw fn 383 kw fn
384 kw use 384 kw use
@@ -406,7 +406,7 @@ fn quux() -> i32 {
406 #[test] 406 #[test]
407 fn test_keywords_after_unsafe_in_item_list() { 407 fn test_keywords_after_unsafe_in_item_list() {
408 check( 408 check(
409 r"unsafe <|>", 409 r"unsafe $0",
410 expect![[r#" 410 expect![[r#"
411 kw fn 411 kw fn
412 kw trait 412 kw trait
@@ -418,7 +418,7 @@ fn quux() -> i32 {
418 #[test] 418 #[test]
419 fn test_keywords_after_unsafe_in_block_expr() { 419 fn test_keywords_after_unsafe_in_block_expr() {
420 check( 420 check(
421 r"fn my_fn() { unsafe <|> }", 421 r"fn my_fn() { unsafe $0 }",
422 expect![[r#" 422 expect![[r#"
423 kw fn 423 kw fn
424 kw trait 424 kw trait
@@ -430,19 +430,19 @@ fn quux() -> i32 {
430 #[test] 430 #[test]
431 fn test_mut_in_ref_and_in_fn_parameters_list() { 431 fn test_mut_in_ref_and_in_fn_parameters_list() {
432 check( 432 check(
433 r"fn my_fn(&<|>) {}", 433 r"fn my_fn(&$0) {}",
434 expect![[r#" 434 expect![[r#"
435 kw mut 435 kw mut
436 "#]], 436 "#]],
437 ); 437 );
438 check( 438 check(
439 r"fn my_fn(<|>) {}", 439 r"fn my_fn($0) {}",
440 expect![[r#" 440 expect![[r#"
441 kw mut 441 kw mut
442 "#]], 442 "#]],
443 ); 443 );
444 check( 444 check(
445 r"fn my_fn() { let &<|> }", 445 r"fn my_fn() { let &$0 }",
446 expect![[r#" 446 expect![[r#"
447 kw mut 447 kw mut
448 "#]], 448 "#]],
@@ -452,13 +452,13 @@ fn quux() -> i32 {
452 #[test] 452 #[test]
453 fn test_where_keyword() { 453 fn test_where_keyword() {
454 check( 454 check(
455 r"trait A <|>", 455 r"trait A $0",
456 expect![[r#" 456 expect![[r#"
457 kw where 457 kw where
458 "#]], 458 "#]],
459 ); 459 );
460 check( 460 check(
461 r"impl A <|>", 461 r"impl A $0",
462 expect![[r#" 462 expect![[r#"
463 kw where 463 kw where
464 "#]], 464 "#]],
@@ -471,7 +471,7 @@ fn quux() -> i32 {
471 check( 471 check(
472 r#" 472 r#"
473fn test() { 473fn test() {
474 let x = 2; // A comment<|> 474 let x = 2; // A comment$0
475} 475}
476"#, 476"#,
477 expect![[""]], 477 expect![[""]],
@@ -479,7 +479,7 @@ fn test() {
479 check( 479 check(
480 r#" 480 r#"
481/* 481/*
482Some multi-line comment<|> 482Some multi-line comment$0
483*/ 483*/
484"#, 484"#,
485 expect![[""]], 485 expect![[""]],
@@ -487,7 +487,7 @@ Some multi-line comment<|>
487 check( 487 check(
488 r#" 488 r#"
489/// Some doc comment 489/// Some doc comment
490/// let test<|> = 1 490/// let test$0 = 1
491"#, 491"#,
492 expect![[""]], 492 expect![[""]],
493 ); 493 );
@@ -501,7 +501,7 @@ Some multi-line comment<|>
501use std::future::*; 501use std::future::*;
502struct A {} 502struct A {}
503impl Future for A {} 503impl Future for A {}
504fn foo(a: A) { a.<|> } 504fn foo(a: A) { a.$0 }
505 505
506//- /std/lib.rs crate:std 506//- /std/lib.rs crate:std
507pub mod future { 507pub mod future {
@@ -520,7 +520,7 @@ pub mod future {
520use std::future::*; 520use std::future::*;
521fn foo() { 521fn foo() {
522 let a = async {}; 522 let a = async {};
523 a.<|> 523 a.$0
524} 524}
525 525
526//- /std/lib.rs crate:std 526//- /std/lib.rs crate:std
@@ -540,7 +540,7 @@ pub mod future {
540 #[test] 540 #[test]
541 fn after_let() { 541 fn after_let() {
542 check( 542 check(
543 r#"fn main() { let _ = <|> }"#, 543 r#"fn main() { let _ = $0 }"#,
544 expect![[r#" 544 expect![[r#"
545 kw match 545 kw match
546 kw while 546 kw while
@@ -557,7 +557,7 @@ pub mod future {
557 check( 557 check(
558 r#" 558 r#"
559struct Foo { 559struct Foo {
560 <|> 560 $0
561 pub f: i32, 561 pub f: i32,
562} 562}
563"#, 563"#,
@@ -578,7 +578,7 @@ struct Foo {
578} 578}
579fn foo() { 579fn foo() {
580 Foo { 580 Foo {
581 <|> 581 $0
582 } 582 }
583} 583}
584"#, 584"#,
@@ -595,7 +595,7 @@ struct Foo {
595} 595}
596fn foo() { 596fn foo() {
597 Foo { 597 Foo {
598 f: <|> 598 f: $0
599 } 599 }
600} 600}
601"#, 601"#,
diff --git a/crates/completion/src/completions/macro_in_item_position.rs b/crates/completion/src/completions/macro_in_item_position.rs
index 82884a181..2be299ac2 100644
--- a/crates/completion/src/completions/macro_in_item_position.rs
+++ b/crates/completion/src/completions/macro_in_item_position.rs
@@ -31,7 +31,7 @@ mod tests {
31macro_rules! foo { () => {} } 31macro_rules! foo { () => {} }
32fn foo() {} 32fn foo() {}
33 33
34<|> 34$0
35"#, 35"#,
36 expect![[r#" 36 expect![[r#"
37 ma foo!(…) macro_rules! foo 37 ma foo!(…) macro_rules! foo
diff --git a/crates/completion/src/completions/mod_.rs b/crates/completion/src/completions/mod_.rs
index f77864b77..00e951ca9 100644
--- a/crates/completion/src/completions/mod_.rs
+++ b/crates/completion/src/completions/mod_.rs
@@ -1,5 +1,7 @@
1//! Completes mod declarations. 1//! Completes mod declarations.
2 2
3use std::iter;
4
3use hir::{Module, ModuleSource}; 5use hir::{Module, ModuleSource};
4use ide_db::base_db::{SourceDatabaseExt, VfsPath}; 6use ide_db::base_db::{SourceDatabaseExt, VfsPath};
5use ide_db::RootDatabase; 7use ide_db::RootDatabase;
@@ -9,12 +11,11 @@ use crate::{CompletionItem, CompletionItemKind};
9 11
10use crate::{context::CompletionContext, item::CompletionKind, Completions}; 12use crate::{context::CompletionContext, item::CompletionKind, Completions};
11 13
12/// Complete mod declaration, i.e. `mod <|> ;` 14/// Complete mod declaration, i.e. `mod $0 ;`
13pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 15pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
14 let mod_under_caret = match &ctx.mod_declaration_under_caret { 16 let mod_under_caret = match &ctx.mod_declaration_under_caret {
15 Some(mod_under_caret) if mod_under_caret.item_list().is_some() => return None, 17 Some(mod_under_caret) if mod_under_caret.item_list().is_none() => mod_under_caret,
16 Some(mod_under_caret) => mod_under_caret, 18 _ => return None,
17 None => return None,
18 }; 19 };
19 20
20 let _p = profile::span("completion::complete_mod"); 21 let _p = profile::span("completion::complete_mod");
@@ -49,9 +50,13 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
49 .filter_map(|submodule_file| { 50 .filter_map(|submodule_file| {
50 let submodule_path = source_root.path_for_file(&submodule_file)?; 51 let submodule_path = source_root.path_for_file(&submodule_file)?;
51 let directory_with_submodule = submodule_path.parent()?; 52 let directory_with_submodule = submodule_path.parent()?;
52 match submodule_path.name_and_extension()? { 53 let (name, ext) = submodule_path.name_and_extension()?;
53 ("lib", Some("rs")) | ("main", Some("rs")) => None, 54 if ext != Some("rs") {
54 ("mod", Some("rs")) => { 55 return None;
56 }
57 match name {
58 "lib" | "main" => None,
59 "mod" => {
55 if directory_with_submodule.parent()? == directory_to_look_for_submodules { 60 if directory_with_submodule.parent()? == directory_to_look_for_submodules {
56 match directory_with_submodule.name_and_extension()? { 61 match directory_with_submodule.name_and_extension()? {
57 (directory_name, None) => Some(directory_name.to_owned()), 62 (directory_name, None) => Some(directory_name.to_owned()),
@@ -61,9 +66,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
61 None 66 None
62 } 67 }
63 } 68 }
64 (file_name, Some("rs")) 69 file_name if directory_with_submodule == directory_to_look_for_submodules => {
65 if directory_with_submodule == directory_to_look_for_submodules =>
66 {
67 Some(file_name.to_owned()) 70 Some(file_name.to_owned())
68 } 71 }
69 _ => None, 72 _ => None,
@@ -73,7 +76,7 @@ pub(crate) fn complete_mod(acc: &mut Completions, ctx: &CompletionContext) -> Op
73 .for_each(|submodule_name| { 76 .for_each(|submodule_name| {
74 let mut label = submodule_name; 77 let mut label = submodule_name;
75 if mod_under_caret.semicolon_token().is_none() { 78 if mod_under_caret.semicolon_token().is_none() {
76 label.push(';') 79 label.push(';');
77 } 80 }
78 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label) 81 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), &label)
79 .kind(CompletionItemKind::Module) 82 .kind(CompletionItemKind::Module)
@@ -89,11 +92,13 @@ fn directory_to_look_for_submodules(
89 module_file_path: &VfsPath, 92 module_file_path: &VfsPath,
90) -> Option<VfsPath> { 93) -> Option<VfsPath> {
91 let directory_with_module_path = module_file_path.parent()?; 94 let directory_with_module_path = module_file_path.parent()?;
92 let base_directory = match module_file_path.name_and_extension()? { 95 let (name, ext) = module_file_path.name_and_extension()?;
93 ("mod", Some("rs")) | ("lib", Some("rs")) | ("main", Some("rs")) => { 96 if ext != Some("rs") {
94 Some(directory_with_module_path) 97 return None;
95 } 98 }
96 (regular_rust_file_name, Some("rs")) => { 99 let base_directory = match name {
100 "mod" | "lib" | "main" => Some(directory_with_module_path),
101 regular_rust_file_name => {
97 if matches!( 102 if matches!(
98 ( 103 (
99 directory_with_module_path 104 directory_with_module_path
@@ -110,37 +115,25 @@ fn directory_to_look_for_submodules(
110 directory_with_module_path.join(regular_rust_file_name) 115 directory_with_module_path.join(regular_rust_file_name)
111 } 116 }
112 } 117 }
113 _ => None,
114 }?; 118 }?;
115 119
116 let mut resulting_path = base_directory; 120 module_chain_to_containing_module_file(module, db)
117 for module in module_chain_to_containing_module_file(module, db) { 121 .into_iter()
118 if let Some(name) = module.name(db) { 122 .filter_map(|module| module.name(db))
119 resulting_path = resulting_path.join(&name.to_string())?; 123 .try_fold(base_directory, |path, name| path.join(&name.to_string()))
120 }
121 }
122
123 Some(resulting_path)
124} 124}
125 125
126fn module_chain_to_containing_module_file( 126fn module_chain_to_containing_module_file(
127 current_module: Module, 127 current_module: Module,
128 db: &RootDatabase, 128 db: &RootDatabase,
129) -> Vec<Module> { 129) -> Vec<Module> {
130 let mut path = Vec::new(); 130 let mut path =
131 131 iter::successors(Some(current_module), |current_module| current_module.parent(db))
132 let mut current_module = Some(current_module); 132 .take_while(|current_module| {
133 while let Some(ModuleSource::Module(_)) = 133 matches!(current_module.definition_source(db).value, ModuleSource::Module(_))
134 current_module.map(|module| module.definition_source(db).value) 134 })
135 { 135 .collect::<Vec<_>>();
136 if let Some(module) = current_module { 136 path.reverse();
137 path.insert(0, module);
138 current_module = module.parent(db);
139 } else {
140 current_module = None;
141 }
142 }
143
144 path 137 path
145} 138}
146 139
@@ -159,7 +152,7 @@ mod tests {
159 check( 152 check(
160 r#" 153 r#"
161 //- /lib.rs 154 //- /lib.rs
162 mod <|> 155 mod $0
163 //- /foo.rs 156 //- /foo.rs
164 fn foo() {} 157 fn foo() {}
165 //- /foo/ignored_foo.rs 158 //- /foo/ignored_foo.rs
@@ -181,7 +174,7 @@ mod tests {
181 check( 174 check(
182 r#" 175 r#"
183 //- /lib.rs 176 //- /lib.rs
184 mod <|> { 177 mod $0 {
185 178
186 } 179 }
187 //- /foo.rs 180 //- /foo.rs
@@ -196,7 +189,7 @@ mod tests {
196 check( 189 check(
197 r#" 190 r#"
198 //- /main.rs 191 //- /main.rs
199 mod <|> 192 mod $0
200 //- /foo.rs 193 //- /foo.rs
201 fn foo() {} 194 fn foo() {}
202 //- /foo/ignored_foo.rs 195 //- /foo/ignored_foo.rs
@@ -219,7 +212,7 @@ mod tests {
219 r#" 212 r#"
220 //- /main.rs 213 //- /main.rs
221 mod tests { 214 mod tests {
222 mod <|>; 215 mod $0;
223 } 216 }
224 //- /tests/foo.rs 217 //- /tests/foo.rs
225 fn foo() {} 218 fn foo() {}
@@ -237,7 +230,7 @@ mod tests {
237 //- /lib.rs 230 //- /lib.rs
238 mod foo; 231 mod foo;
239 //- /foo.rs 232 //- /foo.rs
240 mod <|>; 233 mod $0;
241 //- /foo/bar.rs 234 //- /foo/bar.rs
242 fn bar() {} 235 fn bar() {}
243 //- /foo/bar/ignored_bar.rs 236 //- /foo/bar/ignored_bar.rs
@@ -262,7 +255,7 @@ mod tests {
262 mod foo; 255 mod foo;
263 //- /foo.rs 256 //- /foo.rs
264 mod bar { 257 mod bar {
265 mod <|> 258 mod $0
266 } 259 }
267 //- /foo/bar/baz.rs 260 //- /foo/bar/baz.rs
268 fn baz() {} 261 fn baz() {}
@@ -288,7 +281,7 @@ mod tests {
288 // //- /src/bin.rs 281 // //- /src/bin.rs
289 // fn main() {} 282 // fn main() {}
290 // //- /src/bin/foo.rs 283 // //- /src/bin/foo.rs
291 // mod <|> 284 // mod $0
292 // //- /src/bin/bar.rs 285 // //- /src/bin/bar.rs
293 // fn bar() {} 286 // fn bar() {}
294 // //- /src/bin/bar/bar_ignored.rs 287 // //- /src/bin/bar/bar_ignored.rs
@@ -307,7 +300,7 @@ mod tests {
307 //- /src/bin.rs crate:main 300 //- /src/bin.rs crate:main
308 fn main() {} 301 fn main() {}
309 //- /src/bin/foo.rs 302 //- /src/bin/foo.rs
310 mod <|> 303 mod $0
311 //- /src/bin/bar.rs 304 //- /src/bin/bar.rs
312 mod foo; 305 mod foo;
313 fn bar() {} 306 fn bar() {}
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs
index eee31098d..595160ff5 100644
--- a/crates/completion/src/completions/pattern.rs
+++ b/crates/completion/src/completions/pattern.rs
@@ -71,7 +71,7 @@ static FOO: E = E::X;
71struct Bar { f: u32 } 71struct Bar { f: u32 }
72 72
73fn foo() { 73fn foo() {
74 match E::X { <|> } 74 match E::X { $0 }
75} 75}
76"#, 76"#,
77 expect![[r#" 77 expect![[r#"
@@ -92,7 +92,7 @@ macro_rules! m { ($e:expr) => { $e } }
92enum E { X } 92enum E { X }
93 93
94fn foo() { 94fn foo() {
95 m!(match E::X { <|> }) 95 m!(match E::X { $0 })
96} 96}
97"#, 97"#,
98 expect![[r#" 98 expect![[r#"
@@ -115,7 +115,7 @@ static FOO: E = E::X;
115struct Bar { f: u32 } 115struct Bar { f: u32 }
116 116
117fn foo() { 117fn foo() {
118 let <|> 118 let $0
119} 119}
120"#, 120"#,
121 expect![[r#" 121 expect![[r#"
@@ -133,7 +133,7 @@ enum E { X }
133static FOO: E = E::X; 133static FOO: E = E::X;
134struct Bar { f: u32 } 134struct Bar { f: u32 }
135 135
136fn foo(<|>) { 136fn foo($0) {
137} 137}
138"#, 138"#,
139 expect![[r#" 139 expect![[r#"
@@ -149,7 +149,7 @@ fn foo(<|>) {
149struct Bar { f: u32 } 149struct Bar { f: u32 }
150 150
151fn foo() { 151fn foo() {
152 let <|> 152 let $0
153} 153}
154"#, 154"#,
155 expect![[r#" 155 expect![[r#"
@@ -165,7 +165,7 @@ fn foo() {
165struct Foo { bar: String, baz: String } 165struct Foo { bar: String, baz: String }
166struct Bar(String, String); 166struct Bar(String, String);
167struct Baz; 167struct Baz;
168fn outer(<|>) {} 168fn outer($0) {}
169"#, 169"#,
170 expect![[r#" 170 expect![[r#"
171 bn Foo Foo { bar$1, baz$2 }: Foo$0 171 bn Foo Foo { bar$1, baz$2 }: Foo$0
@@ -182,7 +182,7 @@ struct Foo { bar: String, baz: String }
182struct Bar(String, String); 182struct Bar(String, String);
183struct Baz; 183struct Baz;
184fn outer() { 184fn outer() {
185 let <|> 185 let $0
186} 186}
187"#, 187"#,
188 expect![[r#" 188 expect![[r#"
@@ -201,7 +201,7 @@ struct Bar(String, String);
201struct Baz; 201struct Baz;
202fn outer() { 202fn outer() {
203 match () { 203 match () {
204 <|> 204 $0
205 } 205 }
206} 206}
207"#, 207"#,
@@ -225,7 +225,7 @@ use foo::*;
225 225
226fn outer() { 226fn outer() {
227 match () { 227 match () {
228 <|> 228 $0
229 } 229 }
230} 230}
231"#, 231"#,
@@ -244,7 +244,7 @@ fn outer() {
244struct Foo(i32); 244struct Foo(i32);
245fn main() { 245fn main() {
246 match Foo(92) { 246 match Foo(92) {
247 <|>(92) => (), 247 $0(92) => (),
248 } 248 }
249} 249}
250"#, 250"#,
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs
index 3883d6d21..9c34ed0b6 100644
--- a/crates/completion/src/completions/postfix.rs
+++ b/crates/completion/src/completions/postfix.rs
@@ -1,8 +1,8 @@
1//! Postfix completions, like `Ok(10).ifl<|>` => `if let Ok() = Ok(10) { <|> }`. 1//! Postfix completions, like `Ok(10).ifl$0` => `if let Ok() = Ok(10) { $0 }`.
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,
@@ -36,11 +35,14 @@ pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
36 None => return, 35 None => return,
37 }; 36 };
38 37
38 let ref_removed_ty =
39 std::iter::successors(Some(receiver_ty.clone()), |ty| ty.remove_ref()).last().unwrap();
40
39 let cap = match ctx.config.snippet_cap { 41 let cap = match ctx.config.snippet_cap {
40 Some(it) => it, 42 Some(it) => it,
41 None => return, 43 None => return,
42 }; 44 };
43 let try_enum = TryEnum::from_ty(&ctx.sema, &receiver_ty); 45 let try_enum = TryEnum::from_ty(&ctx.sema, &ref_removed_ty);
44 if let Some(try_enum) = &try_enum { 46 if let Some(try_enum) = &try_enum {
45 match try_enum { 47 match try_enum {
46 TryEnum::Result => { 48 TryEnum::Result => {
@@ -311,7 +313,7 @@ mod tests {
311 r#" 313 r#"
312fn main() { 314fn main() {
313 let bar = true; 315 let bar = true;
314 bar.<|> 316 bar.$0
315} 317}
316"#, 318"#,
317 expect![[r#" 319 expect![[r#"
@@ -343,7 +345,7 @@ fn foo(elt: bool) -> bool {
343 345
344fn main() { 346fn main() {
345 let bar = true; 347 let bar = true;
346 foo(bar.<|>) 348 foo(bar.$0)
347} 349}
348"#, 350"#,
349 expect![[r#" 351 expect![[r#"
@@ -369,7 +371,7 @@ fn main() {
369 r#" 371 r#"
370fn main() { 372fn main() {
371 let bar: u8 = 12; 373 let bar: u8 = 12;
372 bar.<|> 374 bar.$0
373} 375}
374"#, 376"#,
375 expect![[r#" 377 expect![[r#"
@@ -393,7 +395,7 @@ fn main() {
393 check( 395 check(
394 r#" 396 r#"
395fn main() { 397fn main() {
396 baz.l<|> 398 baz.l$0
397 res 399 res
398} 400}
399"#, 401"#,
@@ -425,7 +427,7 @@ enum Option<T> { Some(T), None }
425 427
426fn main() { 428fn main() {
427 let bar = Option::Some(true); 429 let bar = Option::Some(true);
428 bar.<|> 430 bar.$0
429} 431}
430"#, 432"#,
431 r#" 433 r#"
@@ -450,7 +452,7 @@ enum Result<T, E> { Ok(T), Err(E) }
450 452
451fn main() { 453fn main() {
452 let bar = Result::Ok(true); 454 let bar = Result::Ok(true);
453 bar.<|> 455 bar.$0
454} 456}
455"#, 457"#,
456 r#" 458 r#"
@@ -469,7 +471,7 @@ fn main() {
469 471
470 #[test] 472 #[test]
471 fn postfix_completion_works_for_ambiguous_float_literal() { 473 fn postfix_completion_works_for_ambiguous_float_literal() {
472 check_edit("refm", r#"fn main() { 42.<|> }"#, r#"fn main() { &mut 42 }"#) 474 check_edit("refm", r#"fn main() { 42.$0 }"#, r#"fn main() { &mut 42 }"#)
473 } 475 }
474 476
475 #[test] 477 #[test]
@@ -480,7 +482,7 @@ fn main() {
480macro_rules! m { ($e:expr) => { $e } } 482macro_rules! m { ($e:expr) => { $e } }
481fn main() { 483fn main() {
482 let bar: u8 = 12; 484 let bar: u8 = 12;
483 m!(bar.d<|>) 485 m!(bar.d$0)
484} 486}
485"#, 487"#,
486 r#" 488 r#"
@@ -495,55 +497,68 @@ fn main() {
495 497
496 #[test] 498 #[test]
497 fn postfix_completion_for_references() { 499 fn postfix_completion_for_references() {
498 check_edit("dbg", r#"fn main() { &&42.<|> }"#, r#"fn main() { dbg!(&&42) }"#); 500 check_edit("dbg", r#"fn main() { &&42.$0 }"#, r#"fn main() { dbg!(&&42) }"#);
499 check_edit("refm", r#"fn main() { &&42.<|> }"#, r#"fn main() { &&&mut 42 }"#); 501 check_edit("refm", r#"fn main() { &&42.$0 }"#, r#"fn main() { &&&mut 42 }"#);
502 check_edit(
503 "ifl",
504 r#"
505enum Option<T> { Some(T), None }
506
507fn main() {
508 let bar = &Option::Some(true);
509 bar.$0
510}
511"#,
512 r#"
513enum Option<T> { Some(T), None }
514
515fn main() {
516 let bar = &Option::Some(true);
517 if let Some($1) = bar {
518 $0
519}
520}
521"#,
522 )
500 } 523 }
501 524
502 #[test] 525 #[test]
503 fn postfix_completion_for_format_like_strings() { 526 fn postfix_completion_for_format_like_strings() {
504 check_edit( 527 check_edit(
505 "format", 528 "format",
506 r#"fn main() { "{some_var:?}".<|> }"#, 529 r#"fn main() { "{some_var:?}".$0 }"#,
507 r#"fn main() { format!("{:?}", some_var) }"#, 530 r#"fn main() { format!("{:?}", some_var) }"#,
508 ); 531 );
509 check_edit( 532 check_edit(
510 "panic", 533 "panic",
511 r#"fn main() { "Panic with {a}".<|> }"#, 534 r#"fn main() { "Panic with {a}".$0 }"#,
512 r#"fn main() { panic!("Panic with {}", a) }"#, 535 r#"fn main() { panic!("Panic with {}", a) }"#,
513 ); 536 );
514 check_edit( 537 check_edit(
515 "println", 538 "println",
516 r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".<|> }"#, 539 r#"fn main() { "{ 2+2 } { SomeStruct { val: 1, other: 32 } :?}".$0 }"#,
517 r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#, 540 r#"fn main() { println!("{} {:?}", 2+2, SomeStruct { val: 1, other: 32 }) }"#,
518 ); 541 );
519 check_edit( 542 check_edit(
520 "loge", 543 "loge",
521 r#"fn main() { "{2+2}".<|> }"#, 544 r#"fn main() { "{2+2}".$0 }"#,
522 r#"fn main() { log::error!("{}", 2+2) }"#, 545 r#"fn main() { log::error!("{}", 2+2) }"#,
523 ); 546 );
524 check_edit( 547 check_edit(
525 "logt", 548 "logt",
526 r#"fn main() { "{2+2}".<|> }"#, 549 r#"fn main() { "{2+2}".$0 }"#,
527 r#"fn main() { log::trace!("{}", 2+2) }"#, 550 r#"fn main() { log::trace!("{}", 2+2) }"#,
528 ); 551 );
529 check_edit( 552 check_edit(
530 "logd", 553 "logd",
531 r#"fn main() { "{2+2}".<|> }"#, 554 r#"fn main() { "{2+2}".$0 }"#,
532 r#"fn main() { log::debug!("{}", 2+2) }"#, 555 r#"fn main() { log::debug!("{}", 2+2) }"#,
533 ); 556 );
534 check_edit( 557 check_edit("logi", r#"fn main() { "{2+2}".$0 }"#, r#"fn main() { log::info!("{}", 2+2) }"#);
535 "logi", 558 check_edit("logw", r#"fn main() { "{2+2}".$0 }"#, r#"fn main() { log::warn!("{}", 2+2) }"#);
536 r#"fn main() { "{2+2}".<|> }"#,
537 r#"fn main() { log::info!("{}", 2+2) }"#,
538 );
539 check_edit(
540 "logw",
541 r#"fn main() { "{2+2}".<|> }"#,
542 r#"fn main() { log::warn!("{}", 2+2) }"#,
543 );
544 check_edit( 559 check_edit(
545 "loge", 560 "loge",
546 r#"fn main() { "{2+2}".<|> }"#, 561 r#"fn main() { "{2+2}".$0 }"#,
547 r#"fn main() { log::error!("{}", 2+2) }"#, 562 r#"fn main() { log::error!("{}", 2+2) }"#,
548 ); 563 );
549 } 564 }
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/qualified_path.rs b/crates/completion/src/completions/qualified_path.rs
index 882c4dcbc..fa9e6e810 100644
--- a/crates/completion/src/completions/qualified_path.rs
+++ b/crates/completion/src/completions/qualified_path.rs
@@ -1,4 +1,4 @@
1//! Completion of paths, i.e. `some::prefix::<|>`. 1//! Completion of paths, i.e. `some::prefix::$0`.
2 2
3use hir::{Adt, HasVisibility, PathResolution, ScopeDef}; 3use hir::{Adt, HasVisibility, PathResolution, ScopeDef};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
@@ -38,7 +38,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
38 if let ScopeDef::Unknown = def { 38 if let ScopeDef::Unknown = def {
39 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { 39 if let Some(name_ref) = ctx.name_ref_syntax.as_ref() {
40 if name_ref.syntax().text() == name.to_string().as_str() { 40 if name_ref.syntax().text() == name.to_string().as_str() {
41 // for `use self::foo<|>`, don't suggest `foo` as a completion 41 // for `use self::foo$0`, don't suggest `foo` as a completion
42 mark::hit!(dont_complete_current_use); 42 mark::hit!(dont_complete_current_use);
43 continue; 43 continue;
44 } 44 }
@@ -173,7 +173,7 @@ mod tests {
173 #[test] 173 #[test]
174 fn dont_complete_current_use() { 174 fn dont_complete_current_use() {
175 mark::check!(dont_complete_current_use); 175 mark::check!(dont_complete_current_use);
176 check(r#"use self::foo<|>;"#, expect![[""]]); 176 check(r#"use self::foo$0;"#, expect![[""]]);
177 } 177 }
178 178
179 #[test] 179 #[test]
@@ -181,7 +181,7 @@ mod tests {
181 check( 181 check(
182 r#" 182 r#"
183mod foo { pub struct S; } 183mod foo { pub struct S; }
184use self::{foo::*, bar<|>}; 184use self::{foo::*, bar$0};
185"#, 185"#,
186 expect![[r#" 186 expect![[r#"
187 st S 187 st S
@@ -192,18 +192,18 @@ use self::{foo::*, bar<|>};
192 192
193 #[test] 193 #[test]
194 fn dont_complete_primitive_in_use() { 194 fn dont_complete_primitive_in_use() {
195 check_builtin(r#"use self::<|>;"#, expect![[""]]); 195 check_builtin(r#"use self::$0;"#, expect![[""]]);
196 } 196 }
197 197
198 #[test] 198 #[test]
199 fn dont_complete_primitive_in_module_scope() { 199 fn dont_complete_primitive_in_module_scope() {
200 check_builtin(r#"fn foo() { self::<|> }"#, expect![[""]]); 200 check_builtin(r#"fn foo() { self::$0 }"#, expect![[""]]);
201 } 201 }
202 202
203 #[test] 203 #[test]
204 fn completes_primitives() { 204 fn completes_primitives() {
205 check_builtin( 205 check_builtin(
206 r#"fn main() { let _: <|> = 92; }"#, 206 r#"fn main() { let _: $0 = 92; }"#,
207 expect![[r#" 207 expect![[r#"
208 bt u32 208 bt u32
209 bt bool 209 bt bool
@@ -230,7 +230,7 @@ use self::{foo::*, bar<|>};
230 fn completes_mod_with_same_name_as_function() { 230 fn completes_mod_with_same_name_as_function() {
231 check( 231 check(
232 r#" 232 r#"
233use self::my::<|>; 233use self::my::$0;
234 234
235mod my { pub struct Bar; } 235mod my { pub struct Bar; }
236fn my() {} 236fn my() {}
@@ -245,7 +245,7 @@ fn my() {}
245 fn filters_visibility() { 245 fn filters_visibility() {
246 check( 246 check(
247 r#" 247 r#"
248use self::my::<|>; 248use self::my::$0;
249 249
250mod my { 250mod my {
251 struct Bar; 251 struct Bar;
@@ -264,7 +264,7 @@ mod my {
264 fn completes_use_item_starting_with_self() { 264 fn completes_use_item_starting_with_self() {
265 check( 265 check(
266 r#" 266 r#"
267use self::m::<|>; 267use self::m::$0;
268 268
269mod m { pub struct Bar; } 269mod m { pub struct Bar; }
270"#, 270"#,
@@ -282,7 +282,7 @@ mod m { pub struct Bar; }
282mod foo; 282mod foo;
283struct Spam; 283struct Spam;
284//- /foo.rs 284//- /foo.rs
285use crate::Sp<|> 285use crate::Sp$0
286"#, 286"#,
287 expect![[r#" 287 expect![[r#"
288 md foo 288 md foo
@@ -299,7 +299,7 @@ use crate::Sp<|>
299mod foo; 299mod foo;
300struct Spam; 300struct Spam;
301//- /foo.rs 301//- /foo.rs
302use crate::{Sp<|>}; 302use crate::{Sp$0};
303"#, 303"#,
304 expect![[r#" 304 expect![[r#"
305 md foo 305 md foo
@@ -320,7 +320,7 @@ pub mod bar {
320 } 320 }
321} 321}
322//- /foo.rs 322//- /foo.rs
323use crate::{bar::{baz::Sp<|>}}; 323use crate::{bar::{baz::Sp$0}};
324"#, 324"#,
325 expect![[r#" 325 expect![[r#"
326 st Spam 326 st Spam
@@ -333,7 +333,7 @@ use crate::{bar::{baz::Sp<|>}};
333 check( 333 check(
334 r#" 334 r#"
335enum E { Foo, Bar(i32) } 335enum E { Foo, Bar(i32) }
336fn foo() { let _ = E::<|> } 336fn foo() { let _ = E::$0 }
337"#, 337"#,
338 expect![[r#" 338 expect![[r#"
339 ev Foo () 339 ev Foo ()
@@ -356,7 +356,7 @@ impl S {
356 type T = i32; 356 type T = i32;
357} 357}
358 358
359fn foo() { let _ = S::<|> } 359fn foo() { let _ = S::$0 }
360"#, 360"#,
361 expect![[r#" 361 expect![[r#"
362 fn a() fn a() 362 fn a() fn a()
@@ -384,7 +384,7 @@ mod m {
384 } 384 }
385} 385}
386 386
387fn foo() { let _ = S::<|> } 387fn foo() { let _ = S::$0 }
388"#, 388"#,
389 expect![[r#" 389 expect![[r#"
390 fn public_method() pub(crate) fn public_method() 390 fn public_method() pub(crate) fn public_method()
@@ -401,7 +401,7 @@ fn foo() { let _ = S::<|> }
401enum E {}; 401enum E {};
402impl E { fn m() { } } 402impl E { fn m() { } }
403 403
404fn foo() { let _ = E::<|> } 404fn foo() { let _ = E::$0 }
405 "#, 405 "#,
406 expect![[r#" 406 expect![[r#"
407 fn m() fn m() 407 fn m() fn m()
@@ -416,7 +416,7 @@ fn foo() { let _ = E::<|> }
416union U {}; 416union U {};
417impl U { fn m() { } } 417impl U { fn m() { } }
418 418
419fn foo() { let _ = U::<|> } 419fn foo() { let _ = U::$0 }
420"#, 420"#,
421 expect![[r#" 421 expect![[r#"
422 fn m() fn m() 422 fn m() fn m()
@@ -429,7 +429,7 @@ fn foo() { let _ = U::<|> }
429 check( 429 check(
430 r#" 430 r#"
431//- /main.rs crate:main deps:foo 431//- /main.rs crate:main deps:foo
432use foo::<|>; 432use foo::$0;
433 433
434//- /foo/lib.rs crate:foo 434//- /foo/lib.rs crate:foo
435pub mod bar { pub struct S; } 435pub mod bar { pub struct S; }
@@ -446,7 +446,7 @@ pub mod bar { pub struct S; }
446 r#" 446 r#"
447trait Trait { fn m(); } 447trait Trait { fn m(); }
448 448
449fn foo() { let _ = Trait::<|> } 449fn foo() { let _ = Trait::$0 }
450"#, 450"#,
451 expect![[r#" 451 expect![[r#"
452 fn m() fn m() 452 fn m() fn m()
@@ -463,7 +463,7 @@ trait Trait { fn m(); }
463struct S; 463struct S;
464impl Trait for S {} 464impl Trait for S {}
465 465
466fn foo() { let _ = S::<|> } 466fn foo() { let _ = S::$0 }
467"#, 467"#,
468 expect![[r#" 468 expect![[r#"
469 fn m() fn m() 469 fn m() fn m()
@@ -480,7 +480,7 @@ trait Trait { fn m(); }
480struct S; 480struct S;
481impl Trait for S {} 481impl Trait for S {}
482 482
483fn foo() { let _ = <S as Trait>::<|> } 483fn foo() { let _ = <S as Trait>::$0 }
484"#, 484"#,
485 expect![[r#" 485 expect![[r#"
486 fn m() fn m() 486 fn m() fn m()
@@ -506,7 +506,7 @@ trait Sub: Super {
506 fn submethod(&self) {} 506 fn submethod(&self) {}
507} 507}
508 508
509fn foo<T: Sub>() { T::<|> } 509fn foo<T: Sub>() { T::$0 }
510"#, 510"#,
511 expect![[r#" 511 expect![[r#"
512 ta SubTy type SubTy; 512 ta SubTy type SubTy;
@@ -544,7 +544,7 @@ impl<T> Super for Wrap<T> {}
544impl<T> Sub for Wrap<T> { 544impl<T> Sub for Wrap<T> {
545 fn subfunc() { 545 fn subfunc() {
546 // Should be able to assume `Self: Sub + Super` 546 // Should be able to assume `Self: Sub + Super`
547 Self::<|> 547 Self::$0
548 } 548 }
549} 549}
550"#, 550"#,
@@ -570,7 +570,7 @@ impl S { fn foo() {} }
570type T = S; 570type T = S;
571impl T { fn bar() {} } 571impl T { fn bar() {} }
572 572
573fn main() { T::<|>; } 573fn main() { T::$0; }
574"#, 574"#,
575 expect![[r#" 575 expect![[r#"
576 fn foo() fn foo() 576 fn foo() fn foo()
@@ -586,7 +586,7 @@ fn main() { T::<|>; }
586#[macro_export] 586#[macro_export]
587macro_rules! foo { () => {} } 587macro_rules! foo { () => {} }
588 588
589fn main() { let _ = crate::<|> } 589fn main() { let _ = crate::$0 }
590 "#, 590 "#,
591 expect![[r##" 591 expect![[r##"
592 fn main() fn main() 592 fn main() fn main()
@@ -604,7 +604,7 @@ mod a {
604 const A: usize = 0; 604 const A: usize = 0;
605 mod b { 605 mod b {
606 const B: usize = 0; 606 const B: usize = 0;
607 mod c { use super::super::<|> } 607 mod c { use super::super::$0 }
608 } 608 }
609} 609}
610"#, 610"#,
@@ -619,7 +619,7 @@ mod a {
619 fn completes_reexported_items_under_correct_name() { 619 fn completes_reexported_items_under_correct_name() {
620 check( 620 check(
621 r#" 621 r#"
622fn foo() { self::m::<|> } 622fn foo() { self::m::$0 }
623 623
624mod m { 624mod m {
625 pub use super::p::wrong_fn as right_fn; 625 pub use super::p::wrong_fn as right_fn;
@@ -642,7 +642,7 @@ mod p {
642 check_edit( 642 check_edit(
643 "RightType", 643 "RightType",
644 r#" 644 r#"
645fn foo() { self::m::<|> } 645fn foo() { self::m::$0 }
646 646
647mod m { 647mod m {
648 pub use super::p::wrong_fn as right_fn; 648 pub use super::p::wrong_fn as right_fn;
@@ -677,7 +677,7 @@ mod p {
677 check( 677 check(
678 r#" 678 r#"
679macro_rules! m { ($e:expr) => { $e } } 679macro_rules! m { ($e:expr) => { $e } }
680fn main() { m!(self::f<|>); } 680fn main() { m!(self::f$0); }
681fn foo() {} 681fn foo() {}
682"#, 682"#,
683 expect![[r#" 683 expect![[r#"
@@ -691,7 +691,7 @@ fn foo() {}
691 fn function_mod_share_name() { 691 fn function_mod_share_name() {
692 check( 692 check(
693 r#" 693 r#"
694fn foo() { self::m::<|> } 694fn foo() { self::m::$0 }
695 695
696mod m { 696mod m {
697 pub mod z {} 697 pub mod z {}
@@ -716,7 +716,7 @@ impl<K, V> HashMap<K, V, RandomState> {
716 pub fn new() -> HashMap<K, V, RandomState> { } 716 pub fn new() -> HashMap<K, V, RandomState> { }
717} 717}
718fn foo() { 718fn foo() {
719 HashMap::<|> 719 HashMap::$0
720} 720}
721"#, 721"#,
722 expect![[r#" 722 expect![[r#"
@@ -730,7 +730,7 @@ fn foo() {
730 check( 730 check(
731 r#" 731 r#"
732mod foo { pub struct Foo; } 732mod foo { pub struct Foo; }
733#[foo::<|>] 733#[foo::$0]
734fn f() {} 734fn f() {}
735"#, 735"#,
736 expect![[""]], 736 expect![[""]],
@@ -749,7 +749,7 @@ fn foo(
749} 749}
750 750
751fn main() { 751fn main() {
752 fo<|> 752 fo$0
753} 753}
754"#, 754"#,
755 expect![[r#" 755 expect![[r#"
@@ -770,7 +770,7 @@ enum Foo {
770 770
771impl Foo { 771impl Foo {
772 fn foo(self) { 772 fn foo(self) {
773 Self::<|> 773 Self::$0
774 } 774 }
775} 775}
776"#, 776"#,
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs
index 91bf4a8ad..bb6354ded 100644
--- a/crates/completion/src/completions/record.rs
+++ b/crates/completion/src/completions/record.rs
@@ -20,13 +20,17 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) ->
20 20
21 let missing_fields = ctx.sema.record_literal_missing_fields(record_lit); 21 let missing_fields = ctx.sema.record_literal_missing_fields(record_lit);
22 if impl_default_trait && !missing_fields.is_empty() { 22 if impl_default_trait && !missing_fields.is_empty() {
23 let completion_text = "..Default::default()";
24 let completion_text = completion_text
25 .strip_prefix(ctx.token.to_string().as_str())
26 .unwrap_or(completion_text);
23 acc.add( 27 acc.add(
24 CompletionItem::new( 28 CompletionItem::new(
25 CompletionKind::Snippet, 29 CompletionKind::Snippet,
26 ctx.source_range(), 30 ctx.source_range(),
27 "..Default::default()", 31 "..Default::default()",
28 ) 32 )
29 .insert_text("..Default::default()") 33 .insert_text(completion_text)
30 .kind(CompletionItemKind::Field) 34 .kind(CompletionItemKind::Field)
31 .build(), 35 .build(),
32 ); 36 );
@@ -48,7 +52,10 @@ mod tests {
48 use expect_test::{expect, Expect}; 52 use expect_test::{expect, Expect};
49 use ide_db::helpers::FamousDefs; 53 use ide_db::helpers::FamousDefs;
50 54
51 use crate::{test_utils::completion_list, CompletionKind}; 55 use crate::{
56 test_utils::{self, completion_list},
57 CompletionKind,
58 };
52 59
53 fn check(ra_fixture: &str, expect: Expect) { 60 fn check(ra_fixture: &str, expect: Expect) {
54 let actual = completion_list(ra_fixture, CompletionKind::Reference); 61 let actual = completion_list(ra_fixture, CompletionKind::Reference);
@@ -63,6 +70,18 @@ mod tests {
63 expect.assert_eq(&actual); 70 expect.assert_eq(&actual);
64 } 71 }
65 72
73 fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
74 test_utils::check_edit(
75 what,
76 &format!(
77 "//- /main.rs crate:main deps:core{}\n{}",
78 ra_fixture_before,
79 FamousDefs::FIXTURE,
80 ),
81 &(ra_fixture_after.to_owned() + "\n"),
82 );
83 }
84
66 #[test] 85 #[test]
67 fn test_record_literal_field_default() { 86 fn test_record_literal_field_default() {
68 let test_code = r#" 87 let test_code = r#"
@@ -80,7 +99,7 @@ impl core::default::Default for S {
80fn process(f: S) { 99fn process(f: S) {
81 let other = S { 100 let other = S {
82 foo: 5, 101 foo: 5,
83 .<|> 102 .$0
84 }; 103 };
85} 104}
86"#; 105"#;
@@ -102,6 +121,51 @@ fn process(f: S) {
102 } 121 }
103 122
104 #[test] 123 #[test]
124 fn test_record_literal_field_default_completion() {
125 check_edit(
126 "..Default::default()",
127 r#"
128struct S { foo: u32, bar: usize }
129
130impl core::default::Default for S {
131 fn default() -> Self {
132 S {
133 foo: 0,
134 bar: 0,
135 }
136 }
137}
138
139fn process(f: S) {
140 let other = S {
141 foo: 5,
142 .$0
143 };
144}
145"#,
146 r#"
147struct S { foo: u32, bar: usize }
148
149impl core::default::Default for S {
150 fn default() -> Self {
151 S {
152 foo: 0,
153 bar: 0,
154 }
155 }
156}
157
158fn process(f: S) {
159 let other = S {
160 foo: 5,
161 ..Default::default()
162 };
163}
164"#,
165 );
166 }
167
168 #[test]
105 fn test_record_literal_field_without_default() { 169 fn test_record_literal_field_without_default() {
106 let test_code = r#" 170 let test_code = r#"
107struct S { foo: u32, bar: usize } 171struct S { foo: u32, bar: usize }
@@ -109,7 +173,7 @@ struct S { foo: u32, bar: usize }
109fn process(f: S) { 173fn process(f: S) {
110 let other = S { 174 let other = S {
111 foo: 5, 175 foo: 5,
112 .<|> 176 .$0
113 }; 177 };
114} 178}
115"#; 179"#;
@@ -137,7 +201,7 @@ struct S { foo: u32 }
137 201
138fn process(f: S) { 202fn process(f: S) {
139 match f { 203 match f {
140 S { f<|>: 92 } => (), 204 S { f$0: 92 } => (),
141 } 205 }
142} 206}
143"#, 207"#,
@@ -155,7 +219,7 @@ enum E { S { foo: u32, bar: () } }
155 219
156fn process(e: E) { 220fn process(e: E) {
157 match e { 221 match e {
158 E::S { <|> } => (), 222 E::S { $0 } => (),
159 } 223 }
160} 224}
161"#, 225"#,
@@ -175,7 +239,7 @@ struct S { foo: u32 }
175 239
176fn process(f: S) { 240fn process(f: S) {
177 m!(match f { 241 m!(match f {
178 S { f<|>: 92 } => (), 242 S { f$0: 92 } => (),
179 }) 243 })
180} 244}
181", 245",
@@ -199,7 +263,7 @@ fn main() {
199 foo1: 1, foo2: 2, 263 foo1: 1, foo2: 2,
200 bar: 3, baz: 4, 264 bar: 3, baz: 4,
201 }; 265 };
202 if let S { foo1, foo2: a, <|> } = s {} 266 if let S { foo1, foo2: a, $0 } = s {}
203} 267}
204"#, 268"#,
205 expect![[r#" 269 expect![[r#"
@@ -215,7 +279,7 @@ fn main() {
215 r#" 279 r#"
216struct A { the_field: u32 } 280struct A { the_field: u32 }
217fn foo() { 281fn foo() {
218 A { the<|> } 282 A { the$0 }
219} 283}
220"#, 284"#,
221 expect![[r#" 285 expect![[r#"
@@ -230,7 +294,7 @@ fn foo() {
230 r#" 294 r#"
231enum E { A { a: u32 } } 295enum E { A { a: u32 } }
232fn foo() { 296fn foo() {
233 let _ = E::A { <|> } 297 let _ = E::A { $0 }
234} 298}
235"#, 299"#,
236 expect![[r#" 300 expect![[r#"
@@ -247,7 +311,7 @@ struct A { a: u32 }
247struct B { b: u32 } 311struct B { b: u32 }
248 312
249fn foo() { 313fn foo() {
250 let _: A = B { <|> } 314 let _: A = B { $0 }
251} 315}
252"#, 316"#,
253 expect![[r#" 317 expect![[r#"
@@ -263,7 +327,7 @@ fn foo() {
263struct A<T> { a: T } 327struct A<T> { a: T }
264 328
265fn foo() { 329fn foo() {
266 let _: A<u32> = A { <|> } 330 let _: A<u32> = A { $0 }
267} 331}
268"#, 332"#,
269 expect![[r#" 333 expect![[r#"
@@ -279,7 +343,7 @@ fn foo() {
279macro_rules! m { ($e:expr) => { $e } } 343macro_rules! m { ($e:expr) => { $e } }
280struct A { the_field: u32 } 344struct A { the_field: u32 }
281fn foo() { 345fn foo() {
282 m!(A { the<|> }) 346 m!(A { the$0 })
283} 347}
284"#, 348"#,
285 expect![[r#" 349 expect![[r#"
@@ -299,7 +363,7 @@ struct S {
299 363
300fn main() { 364fn main() {
301 let foo1 = 1; 365 let foo1 = 1;
302 let s = S { foo1, foo2: 5, <|> } 366 let s = S { foo1, foo2: 5, $0 }
303} 367}
304"#, 368"#,
305 expect![[r#" 369 expect![[r#"
@@ -317,7 +381,7 @@ struct S { foo1: u32, foo2: u32 }
317 381
318fn main() { 382fn main() {
319 let foo1 = 1; 383 let foo1 = 1;
320 let s = S { foo1, <|> .. loop {} } 384 let s = S { foo1, $0 .. loop {} }
321} 385}
322"#, 386"#,
323 expect![[r#" 387 expect![[r#"
diff --git a/crates/completion/src/completions/snippet.rs b/crates/completion/src/completions/snippet.rs
index 842590130..df17a15c5 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 {
@@ -81,7 +83,7 @@ mod tests {
81 #[test] 83 #[test]
82 fn completes_snippets_in_expressions() { 84 fn completes_snippets_in_expressions() {
83 check( 85 check(
84 r#"fn foo(x: i32) { <|> }"#, 86 r#"fn foo(x: i32) { $0 }"#,
85 expect![[r#" 87 expect![[r#"
86 sn pd 88 sn pd
87 sn ppd 89 sn ppd
@@ -91,8 +93,8 @@ mod tests {
91 93
92 #[test] 94 #[test]
93 fn should_not_complete_snippets_in_path() { 95 fn should_not_complete_snippets_in_path() {
94 check(r#"fn foo(x: i32) { ::foo<|> }"#, expect![[""]]); 96 check(r#"fn foo(x: i32) { ::foo$0 }"#, expect![[""]]);
95 check(r#"fn foo(x: i32) { ::<|> }"#, expect![[""]]); 97 check(r#"fn foo(x: i32) { ::$0 }"#, expect![[""]]);
96 } 98 }
97 99
98 #[test] 100 #[test]
@@ -101,7 +103,7 @@ mod tests {
101 r#" 103 r#"
102#[cfg(test)] 104#[cfg(test)]
103mod tests { 105mod tests {
104 <|> 106 $0
105} 107}
106"#, 108"#,
107 expect![[r#" 109 expect![[r#"
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs
index c4e0d0669..135ae49dc 100644
--- a/crates/completion/src/completions/trait_impl.rs
+++ b/crates/completion/src/completions/trait_impl.rs
@@ -15,7 +15,7 @@
15//! } 15//! }
16//! 16//!
17//! impl SomeTrait for () { 17//! impl SomeTrait for () {
18//! fn f<|> 18//! fn f$0
19//! } 19//! }
20//! ``` 20//! ```
21//! 21//!
@@ -27,7 +27,7 @@
27//! # } 27//! # }
28//! 28//!
29//! impl SomeTrait for () { 29//! impl SomeTrait for () {
30//! fn foo() {}<|> 30//! fn foo() {}$0
31//! } 31//! }
32//! ``` 32//! ```
33 33
@@ -82,7 +82,7 @@ pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext
82 82
83fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> { 83fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, SyntaxNode, Impl)> {
84 let mut token = ctx.token.clone(); 84 let mut token = ctx.token.clone();
85 // For keywork without name like `impl .. { fn <|> }`, the current position is inside 85 // For keywork without name like `impl .. { fn $0 }`, the current position is inside
86 // the whitespace token, which is outside `FN` syntax node. 86 // the whitespace token, which is outside `FN` syntax node.
87 // We need to follow the previous token in this case. 87 // We need to follow the previous token in this case.
88 if token.kind() == SyntaxKind::WHITESPACE { 88 if token.kind() == SyntaxKind::WHITESPACE {
@@ -90,20 +90,20 @@ fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, Synt
90 } 90 }
91 91
92 let impl_item_offset = match token.kind() { 92 let impl_item_offset = match token.kind() {
93 // `impl .. { const <|> }` 93 // `impl .. { const $0 }`
94 // ERROR 0 94 // ERROR 0
95 // CONST_KW <- * 95 // CONST_KW <- *
96 SyntaxKind::CONST_KW => 0, 96 T![const] => 0,
97 // `impl .. { fn/type <|> }` 97 // `impl .. { fn/type $0 }`
98 // FN/TYPE_ALIAS 0 98 // FN/TYPE_ALIAS 0
99 // FN_KW <- * 99 // FN_KW <- *
100 SyntaxKind::FN_KW | SyntaxKind::TYPE_KW => 0, 100 T![fn] | T![type] => 0,
101 // `impl .. { fn/type/const foo<|> }` 101 // `impl .. { fn/type/const foo$0 }`
102 // FN/TYPE_ALIAS/CONST 1 102 // FN/TYPE_ALIAS/CONST 1
103 // NAME 0 103 // NAME 0
104 // IDENT <- * 104 // IDENT <- *
105 SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1, 105 SyntaxKind::IDENT if token.parent().kind() == SyntaxKind::NAME => 1,
106 // `impl .. { foo<|> }` 106 // `impl .. { foo$0 }`
107 // MACRO_CALL 3 107 // MACRO_CALL 3
108 // PATH 2 108 // PATH 2
109 // PATH_SEGMENT 1 109 // PATH_SEGMENT 1
@@ -120,8 +120,8 @@ fn completion_match(ctx: &CompletionContext) -> Option<(ImplCompletionKind, Synt
120 // <item> 120 // <item>
121 let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?; 121 let impl_def = ast::Impl::cast(impl_item.parent()?.parent()?)?;
122 let kind = match impl_item.kind() { 122 let kind = match impl_item.kind() {
123 // `impl ... { const <|> fn/type/const }` 123 // `impl ... { const $0 fn/type/const }`
124 _ if token.kind() == SyntaxKind::CONST_KW => ImplCompletionKind::Const, 124 _ if token.kind() == T![const] => ImplCompletionKind::Const,
125 SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const, 125 SyntaxKind::CONST | SyntaxKind::ERROR => ImplCompletionKind::Const,
126 SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias, 126 SyntaxKind::TYPE_ALIAS => ImplCompletionKind::TypeAlias,
127 SyntaxKind::FN => ImplCompletionKind::Fn, 127 SyntaxKind::FN => ImplCompletionKind::Fn,
@@ -156,19 +156,21 @@ fn add_function_impl(
156 }; 156 };
157 let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); 157 let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end());
158 158
159 let function_decl = function_declaration(&func.source(ctx.db).value); 159 if let Some(src) = func.source(ctx.db) {
160 match ctx.config.snippet_cap { 160 let function_decl = function_declaration(&src.value);
161 Some(cap) => { 161 match ctx.config.snippet_cap {
162 let snippet = format!("{} {{\n $0\n}}", function_decl); 162 Some(cap) => {
163 builder.snippet_edit(cap, TextEdit::replace(range, snippet)) 163 let snippet = format!("{} {{\n $0\n}}", function_decl);
164 } 164 builder.snippet_edit(cap, TextEdit::replace(range, snippet))
165 None => { 165 }
166 let header = format!("{} {{", function_decl); 166 None => {
167 builder.text_edit(TextEdit::replace(range, header)) 167 let header = format!("{} {{", function_decl);
168 builder.text_edit(TextEdit::replace(range, header))
169 }
168 } 170 }
171 .kind(completion_kind)
172 .add_to(acc);
169 } 173 }
170 .kind(completion_kind)
171 .add_to(acc);
172} 174}
173 175
174fn add_type_alias_impl( 176fn add_type_alias_impl(
@@ -200,16 +202,19 @@ fn add_const_impl(
200 let const_name = const_.name(ctx.db).map(|n| n.to_string()); 202 let const_name = const_.name(ctx.db).map(|n| n.to_string());
201 203
202 if let Some(const_name) = const_name { 204 if let Some(const_name) = const_name {
203 let snippet = make_const_compl_syntax(&const_.source(ctx.db).value); 205 if let Some(source) = const_.source(ctx.db) {
204 206 let snippet = make_const_compl_syntax(&source.value);
205 let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); 207
206 208 let range =
207 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) 209 TextRange::new(const_def_node.text_range().start(), ctx.source_range().end());
208 .text_edit(TextEdit::replace(range, snippet)) 210
209 .lookup_by(const_name) 211 CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
210 .kind(CompletionItemKind::Const) 212 .text_edit(TextEdit::replace(range, snippet))
211 .set_documentation(const_.docs(ctx.db)) 213 .lookup_by(const_name)
212 .add_to(acc); 214 .kind(CompletionItemKind::Const)
215 .set_documentation(const_.docs(ctx.db))
216 .add_to(acc);
217 }
213 } 218 }
214} 219}
215 220
@@ -262,7 +267,7 @@ trait Test {
262struct T; 267struct T;
263 268
264impl Test for T { 269impl Test for T {
265 t<|> 270 t$0
266} 271}
267"#, 272"#,
268 expect![[" 273 expect![["
@@ -282,7 +287,7 @@ struct T;
282 287
283impl Test for T { 288impl Test for T {
284 fn test() { 289 fn test() {
285 t<|> 290 t$0
286 } 291 }
287} 292}
288", 293",
@@ -296,7 +301,7 @@ struct T;
296 301
297impl Test for T { 302impl Test for T {
298 fn test() { 303 fn test() {
299 fn t<|> 304 fn t$0
300 } 305 }
301} 306}
302", 307",
@@ -310,7 +315,7 @@ struct T;
310 315
311impl Test for T { 316impl Test for T {
312 fn test() { 317 fn test() {
313 fn <|> 318 fn $0
314 } 319 }
315} 320}
316", 321",
@@ -325,7 +330,7 @@ struct T;
325 330
326impl Test for T { 331impl Test for T {
327 fn test() { 332 fn test() {
328 foo.<|> 333 foo.$0
329 } 334 }
330} 335}
331", 336",
@@ -338,7 +343,7 @@ trait Test { fn test(_: i32); fn test2(); }
338struct T; 343struct T;
339 344
340impl Test for T { 345impl Test for T {
341 fn test(t<|>) 346 fn test(t$0)
342} 347}
343", 348",
344 expect![[""]], 349 expect![[""]],
@@ -350,7 +355,7 @@ trait Test { fn test(_: fn()); fn test2(); }
350struct T; 355struct T;
351 356
352impl Test for T { 357impl Test for T {
353 fn test(f: fn <|>) 358 fn test(f: fn $0)
354} 359}
355", 360",
356 expect![[""]], 361 expect![[""]],
@@ -365,7 +370,7 @@ trait Test { const TEST: fn(); const TEST2: u32; type Test; fn test(); }
365struct T; 370struct T;
366 371
367impl Test for T { 372impl Test for T {
368 const TEST: fn <|> 373 const TEST: fn $0
369} 374}
370", 375",
371 expect![[""]], 376 expect![[""]],
@@ -377,7 +382,7 @@ trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
377struct T; 382struct T;
378 383
379impl Test for T { 384impl Test for T {
380 const TEST: T<|> 385 const TEST: T$0
381} 386}
382", 387",
383 expect![[""]], 388 expect![[""]],
@@ -389,7 +394,7 @@ trait Test { const TEST: u32; const TEST2: u32; type Test; fn test(); }
389struct T; 394struct T;
390 395
391impl Test for T { 396impl Test for T {
392 const TEST: u32 = f<|> 397 const TEST: u32 = f$0
393} 398}
394", 399",
395 expect![[""]], 400 expect![[""]],
@@ -402,7 +407,7 @@ struct T;
402 407
403impl Test for T { 408impl Test for T {
404 const TEST: u32 = { 409 const TEST: u32 = {
405 t<|> 410 t$0
406 }; 411 };
407} 412}
408", 413",
@@ -416,7 +421,7 @@ struct T;
416 421
417impl Test for T { 422impl Test for T {
418 const TEST: u32 = { 423 const TEST: u32 = {
419 fn <|> 424 fn $0
420 }; 425 };
421} 426}
422", 427",
@@ -430,7 +435,7 @@ struct T;
430 435
431impl Test for T { 436impl Test for T {
432 const TEST: u32 = { 437 const TEST: u32 = {
433 fn t<|> 438 fn t$0
434 }; 439 };
435} 440}
436", 441",
@@ -446,7 +451,7 @@ trait Test { type Test; type Test2; fn test(); }
446struct T; 451struct T;
447 452
448impl Test for T { 453impl Test for T {
449 type Test = T<|>; 454 type Test = T$0;
450} 455}
451", 456",
452 expect![[""]], 457 expect![[""]],
@@ -458,7 +463,7 @@ trait Test { type Test; type Test2; fn test(); }
458struct T; 463struct T;
459 464
460impl Test for T { 465impl Test for T {
461 type Test = fn <|>; 466 type Test = fn $0;
462} 467}
463", 468",
464 expect![[""]], 469 expect![[""]],
@@ -476,7 +481,7 @@ trait Test {
476struct T; 481struct T;
477 482
478impl Test for T { 483impl Test for T {
479 t<|> 484 t$0
480} 485}
481"#, 486"#,
482 r#" 487 r#"
@@ -505,7 +510,7 @@ trait Test {
505struct T; 510struct T;
506 511
507impl Test for T { 512impl Test for T {
508 fn t<|> 513 fn t$0
509} 514}
510"#, 515"#,
511 r#" 516 r#"
@@ -535,7 +540,7 @@ struct T;
535 540
536impl Test for T { 541impl Test for T {
537 fn foo() {} 542 fn foo() {}
538 fn f<|> 543 fn f$0
539} 544}
540"#, 545"#,
541 expect![[r#" 546 expect![[r#"
@@ -555,7 +560,7 @@ trait Test {
555struct T; 560struct T;
556 561
557impl Test for T { 562impl Test for T {
558 fn f<|> 563 fn f$0
559} 564}
560"#, 565"#,
561 r#" 566 r#"
@@ -580,7 +585,7 @@ trait Test {
580struct T; 585struct T;
581 586
582impl Test for T { 587impl Test for T {
583 fn f<|> 588 fn f$0
584} 589}
585"#, 590"#,
586 r#" 591 r#"
@@ -609,7 +614,7 @@ trait Test {
609} 614}
610 615
611impl Test for () { 616impl Test for () {
612 type S<|> 617 type S$0
613} 618}
614"#, 619"#,
615 " 620 "
@@ -634,7 +639,7 @@ trait Test {
634} 639}
635 640
636impl Test for () { 641impl Test for () {
637 const S<|> 642 const S$0
638} 643}
639"#, 644"#,
640 " 645 "
@@ -656,7 +661,7 @@ trait Test {
656} 661}
657 662
658impl Test for () { 663impl Test for () {
659 const S<|> 664 const S$0
660} 665}
661"#, 666"#,
662 " 667 "
@@ -719,7 +724,7 @@ impl Test for T {{
719 // Enumerate some possible next siblings. 724 // Enumerate some possible next siblings.
720 for next_sibling in &[ 725 for next_sibling in &[
721 "", 726 "",
722 "fn other_fn() {}", // `const <|> fn` -> `const fn` 727 "fn other_fn() {}", // `const $0 fn` -> `const fn`
723 "type OtherType = i32;", 728 "type OtherType = i32;",
724 "const OTHER_CONST: i32 = 0;", 729 "const OTHER_CONST: i32 = 0;",
725 "async fn other_fn() {}", 730 "async fn other_fn() {}",
@@ -728,9 +733,9 @@ impl Test for T {{
728 "default type OtherType = i32;", 733 "default type OtherType = i32;",
729 "default const OTHER_CONST: i32 = 0;", 734 "default const OTHER_CONST: i32 = 0;",
730 ] { 735 ] {
731 test("bar", "fn <|>", "fn bar() {\n $0\n}", next_sibling); 736 test("bar", "fn $0", "fn bar() {\n $0\n}", next_sibling);
732 test("Foo", "type <|>", "type Foo = ", next_sibling); 737 test("Foo", "type $0", "type Foo = ", next_sibling);
733 test("CONST", "const <|>", "const CONST: u16 = ", next_sibling); 738 test("CONST", "const $0", "const CONST: u16 = ", next_sibling);
734 } 739 }
735 } 740 }
736} 741}
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs
index 81a6d00e2..12cdb869d 100644
--- a/crates/completion/src/completions/unqualified_path.rs
+++ b/crates/completion/src/completions/unqualified_path.rs
@@ -46,7 +46,7 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
46 acc.add_resolution(ctx, name.to_string(), &res) 46 acc.add_resolution(ctx, name.to_string(), &res)
47 }); 47 });
48 48
49 if ctx.config.enable_autoimport_completions && ctx.config.resolve_additional_edits_lazily() { 49 if ctx.config.enable_autoimport_completions {
50 fuzzy_completion(acc, ctx); 50 fuzzy_completion(acc, ctx);
51 } 51 }
52} 52}
@@ -85,7 +85,7 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
85// 85//
86// ``` 86// ```
87// fn main() { 87// fn main() {
88// pda<|> 88// pda$0
89// } 89// }
90// # pub mod std { pub mod marker { pub struct PhantomData { } } } 90// # pub mod std { pub mod marker { pub struct PhantomData { } } }
91// ``` 91// ```
@@ -124,8 +124,8 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T
124// Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding 124// Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
125// capability enabled. 125// capability enabled.
126fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 126fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
127 let _p = profile::span("fuzzy_completion");
128 let potential_import_name = ctx.token.to_string(); 127 let potential_import_name = ctx.token.to_string();
128 let _p = profile::span("fuzzy_completion").detail(|| potential_import_name.clone());
129 129
130 if potential_import_name.len() < 2 { 130 if potential_import_name.len() < 2 {
131 return None; 131 return None;
@@ -142,6 +142,7 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<()
142 Some(40), 142 Some(40),
143 potential_import_name, 143 potential_import_name,
144 true, 144 true,
145 true,
145 ) 146 )
146 .filter_map(|import_candidate| { 147 .filter_map(|import_candidate| {
147 Some(match import_candidate { 148 Some(match import_candidate {
@@ -191,12 +192,14 @@ mod tests {
191 use test_utils::mark; 192 use test_utils::mark;
192 193
193 use crate::{ 194 use crate::{
194 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 },
195 CompletionConfig, CompletionKind, 198 CompletionConfig, CompletionKind,
196 }; 199 };
197 200
198 fn check(ra_fixture: &str, expect: Expect) { 201 fn check(ra_fixture: &str, expect: Expect) {
199 check_with_config(CompletionConfig::default(), ra_fixture, expect); 202 check_with_config(TEST_CONFIG, ra_fixture, expect);
200 } 203 }
201 204
202 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) { 205 fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
@@ -204,20 +207,12 @@ mod tests {
204 expect.assert_eq(&actual) 207 expect.assert_eq(&actual)
205 } 208 }
206 209
207 fn fuzzy_completion_config() -> CompletionConfig {
208 let mut completion_config = CompletionConfig::default();
209 completion_config
210 .active_resolve_capabilities
211 .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
212 completion_config
213 }
214
215 #[test] 210 #[test]
216 fn self_fulfilling_completion() { 211 fn self_fulfilling_completion() {
217 mark::check!(self_fulfilling_completion); 212 mark::check!(self_fulfilling_completion);
218 check( 213 check(
219 r#" 214 r#"
220use foo<|> 215use foo$0
221use std::collections; 216use std::collections;
222"#, 217"#,
223 expect![[r#" 218 expect![[r#"
@@ -234,7 +229,7 @@ enum Enum { A, B }
234fn quux(x: Option<Enum>) { 229fn quux(x: Option<Enum>) {
235 match x { 230 match x {
236 None => (), 231 None => (),
237 Some(en<|> @ Enum::A) => (), 232 Some(en$0 @ Enum::A) => (),
238 } 233 }
239} 234}
240"#, 235"#,
@@ -250,7 +245,7 @@ enum Enum { A, B }
250fn quux(x: Option<Enum>) { 245fn quux(x: Option<Enum>) {
251 match x { 246 match x {
252 None => (), 247 None => (),
253 Some(ref en<|>) => (), 248 Some(ref en$0) => (),
254 } 249 }
255} 250}
256"#, 251"#,
@@ -266,7 +261,7 @@ enum Enum { A, B }
266fn quux(x: Option<Enum>) { 261fn quux(x: Option<Enum>) {
267 match x { 262 match x {
268 None => (), 263 None => (),
269 Some(En<|>) => (), 264 Some(En$0) => (),
270 } 265 }
271} 266}
272"#, 267"#,
@@ -282,7 +277,7 @@ fn quux(x: Option<Enum>) {
282 r#" 277 r#"
283fn quux(x: i32) { 278fn quux(x: i32) {
284 let y = 92; 279 let y = 92;
285 1 + <|>; 280 1 + $0;
286 let z = (); 281 let z = ();
287} 282}
288"#, 283"#,
@@ -304,7 +299,7 @@ fn quux() {
304 }; 299 };
305 if let Some(a) = bar() { 300 if let Some(a) = bar() {
306 let b = 62; 301 let b = 62;
307 1 + <|> 302 1 + $0
308 } 303 }
309} 304}
310"#, 305"#,
@@ -321,7 +316,7 @@ fn quux() {
321 check( 316 check(
322 r#" 317 r#"
323fn quux() { 318fn quux() {
324 for x in &[1, 2, 3] { <|> } 319 for x in &[1, 2, 3] { $0 }
325} 320}
326"#, 321"#,
327 expect![[r#" 322 expect![[r#"
@@ -339,7 +334,7 @@ fn quux() {
339 r#" 334 r#"
340fn main() { 335fn main() {
341 let wherewolf = 92; 336 let wherewolf = 92;
342 drop(where<|>) 337 drop(where$0)
343} 338}
344"#, 339"#,
345 r#" 340 r#"
@@ -354,7 +349,7 @@ fn main() {
354 #[test] 349 #[test]
355 fn completes_generic_params() { 350 fn completes_generic_params() {
356 check( 351 check(
357 r#"fn quux<T>() { <|> }"#, 352 r#"fn quux<T>() { $0 }"#,
358 expect![[r#" 353 expect![[r#"
359 tp T 354 tp T
360 fn quux() fn quux<T>() 355 fn quux() fn quux<T>()
@@ -365,7 +360,7 @@ fn main() {
365 #[test] 360 #[test]
366 fn completes_generic_params_in_struct() { 361 fn completes_generic_params_in_struct() {
367 check( 362 check(
368 r#"struct S<T> { x: <|>}"#, 363 r#"struct S<T> { x: $0}"#,
369 expect![[r#" 364 expect![[r#"
370 tp Self 365 tp Self
371 tp T 366 tp T
@@ -377,7 +372,7 @@ fn main() {
377 #[test] 372 #[test]
378 fn completes_self_in_enum() { 373 fn completes_self_in_enum() {
379 check( 374 check(
380 r#"enum X { Y(<|>) }"#, 375 r#"enum X { Y($0) }"#,
381 expect![[r#" 376 expect![[r#"
382 tp Self 377 tp Self
383 en X 378 en X
@@ -391,7 +386,7 @@ fn main() {
391 r#" 386 r#"
392struct S; 387struct S;
393enum E {} 388enum E {}
394fn quux() { <|> } 389fn quux() { $0 }
395"#, 390"#,
396 expect![[r#" 391 expect![[r#"
397 st S 392 st S
@@ -408,7 +403,7 @@ fn quux() { <|> }
408 "_alpha", 403 "_alpha",
409 r#" 404 r#"
410fn main() { 405fn main() {
411 _<|> 406 _$0
412} 407}
413fn _alpha() {} 408fn _alpha() {}
414"#, 409"#,
@@ -426,7 +421,7 @@ fn _alpha() {}
426 check( 421 check(
427 r#" 422 r#"
428//- /lib.rs crate:main deps:other_crate 423//- /lib.rs crate:main deps:other_crate
429use <|>; 424use $0;
430 425
431//- /other_crate/lib.rs crate:other_crate 426//- /other_crate/lib.rs crate:other_crate
432// nothing here 427// nothing here
@@ -444,7 +439,7 @@ use <|>;
444struct Foo; 439struct Foo;
445mod m { 440mod m {
446 struct Bar; 441 struct Bar;
447 fn quux() { <|> } 442 fn quux() { $0 }
448} 443}
449"#, 444"#,
450 expect![[r#" 445 expect![[r#"
@@ -459,7 +454,7 @@ mod m {
459 check( 454 check(
460 r#" 455 r#"
461struct Foo; 456struct Foo;
462fn x() -> <|> 457fn x() -> $0
463"#, 458"#,
464 expect![[r#" 459 expect![[r#"
465 st Foo 460 st Foo
@@ -476,7 +471,7 @@ fn foo() {
476 let bar = 92; 471 let bar = 92;
477 { 472 {
478 let bar = 62; 473 let bar = 62;
479 drop(<|>) 474 drop($0)
480 } 475 }
481} 476}
482"#, 477"#,
@@ -492,7 +487,7 @@ fn foo() {
492 #[test] 487 #[test]
493 fn completes_self_in_methods() { 488 fn completes_self_in_methods() {
494 check( 489 check(
495 r#"impl S { fn foo(&self) { <|> } }"#, 490 r#"impl S { fn foo(&self) { $0 } }"#,
496 expect![[r#" 491 expect![[r#"
497 bn self &{unknown} 492 bn self &{unknown}
498 tp Self 493 tp Self
@@ -505,7 +500,7 @@ fn foo() {
505 check( 500 check(
506 r#" 501 r#"
507//- /main.rs crate:main deps:std 502//- /main.rs crate:main deps:std
508fn foo() { let x: <|> } 503fn foo() { let x: $0 }
509 504
510//- /std/lib.rs crate:std 505//- /std/lib.rs crate:std
511#[prelude_import] 506#[prelude_import]
@@ -526,7 +521,7 @@ mod prelude { struct Option; }
526 check( 521 check(
527 r#" 522 r#"
528//- /main.rs crate:main deps:core,std 523//- /main.rs crate:main deps:core,std
529fn foo() { let x: <|> } 524fn foo() { let x: $0 }
530 525
531//- /core/lib.rs crate:core 526//- /core/lib.rs crate:core
532#[prelude_import] 527#[prelude_import]
@@ -567,7 +562,7 @@ mod m2 {
567 macro_rules! baz { () => {} } 562 macro_rules! baz { () => {} }
568} 563}
569 564
570fn main() { let v = <|> } 565fn main() { let v = $0 }
571"#, 566"#,
572 expect![[r##" 567 expect![[r##"
573 md m1 568 md m1
@@ -586,7 +581,7 @@ fn main() { let v = <|> }
586 check( 581 check(
587 r#" 582 r#"
588macro_rules! foo { () => {} } 583macro_rules! foo { () => {} }
589fn foo() { <|> } 584fn foo() { $0 }
590"#, 585"#,
591 expect![[r#" 586 expect![[r#"
592 fn foo() fn foo() 587 fn foo() fn foo()
@@ -600,7 +595,7 @@ fn foo() { <|> }
600 check( 595 check(
601 r#" 596 r#"
602macro_rules! foo { () => {} } 597macro_rules! foo { () => {} }
603fn main() { let x: <|> } 598fn main() { let x: $0 }
604"#, 599"#,
605 expect![[r#" 600 expect![[r#"
606 fn main() fn main() 601 fn main() fn main()
@@ -614,7 +609,7 @@ fn main() { let x: <|> }
614 check( 609 check(
615 r#" 610 r#"
616macro_rules! foo { () => {} } 611macro_rules! foo { () => {} }
617fn main() { <|> } 612fn main() { $0 }
618"#, 613"#,
619 expect![[r#" 614 expect![[r#"
620 fn main() fn main() 615 fn main() fn main()
@@ -628,7 +623,7 @@ fn main() { <|> }
628 check( 623 check(
629 r#" 624 r#"
630fn main() { 625fn main() {
631 return f<|>; 626 return f$0;
632 fn frobnicate() {} 627 fn frobnicate() {}
633} 628}
634"#, 629"#,
@@ -646,7 +641,7 @@ fn main() {
646macro_rules! m { ($e:expr) => { $e } } 641macro_rules! m { ($e:expr) => { $e } }
647fn quux(x: i32) { 642fn quux(x: i32) {
648 let y = 92; 643 let y = 92;
649 m!(<|>); 644 m!($0);
650} 645}
651"#, 646"#,
652 expect![[r#" 647 expect![[r#"
@@ -665,7 +660,7 @@ fn quux(x: i32) {
665macro_rules! m { ($e:expr) => { $e } } 660macro_rules! m { ($e:expr) => { $e } }
666fn quux(x: i32) { 661fn quux(x: i32) {
667 let y = 92; 662 let y = 92;
668 m!(x<|>); 663 m!(x$0);
669} 664}
670", 665",
671 expect![[r#" 666 expect![[r#"
@@ -684,7 +679,7 @@ fn quux(x: i32) {
684macro_rules! m { ($e:expr) => { $e } } 679macro_rules! m { ($e:expr) => { $e } }
685fn quux(x: i32) { 680fn quux(x: i32) {
686 let y = 92; 681 let y = 92;
687 m!(x<|> 682 m!(x$0
688} 683}
689"#, 684"#,
690 expect![[r#" 685 expect![[r#"
@@ -702,7 +697,7 @@ fn quux(x: i32) {
702 r#" 697 r#"
703use spam::Quux; 698use spam::Quux;
704 699
705fn main() { <|> } 700fn main() { $0 }
706"#, 701"#,
707 expect![[r#" 702 expect![[r#"
708 fn main() fn main() 703 fn main() fn main()
@@ -719,7 +714,7 @@ enum Foo { Bar, Baz, Quux }
719 714
720fn main() { 715fn main() {
721 let foo = Foo::Quux; 716 let foo = Foo::Quux;
722 match foo { Qu<|> } 717 match foo { Qu$0 }
723} 718}
724"#, 719"#,
725 expect![[r#" 720 expect![[r#"
@@ -739,7 +734,7 @@ enum Foo { Bar, Baz, Quux }
739 734
740fn main() { 735fn main() {
741 let foo = Foo::Quux; 736 let foo = Foo::Quux;
742 match &foo { Qu<|> } 737 match &foo { Qu$0 }
743} 738}
744"#, 739"#,
745 expect![[r#" 740 expect![[r#"
@@ -759,7 +754,7 @@ enum Foo { Bar, Baz, Quux }
759 754
760fn main() { 755fn main() {
761 let foo = Foo::Quux; 756 let foo = Foo::Quux;
762 if let Qu<|> = foo { } 757 if let Qu$0 = foo { }
763} 758}
764"#, 759"#,
765 expect![[r#" 760 expect![[r#"
@@ -776,7 +771,7 @@ fn main() {
776 check( 771 check(
777 r#" 772 r#"
778enum Foo { Bar, Baz, Quux } 773enum Foo { Bar, Baz, Quux }
779fn main() { let foo: Foo = Q<|> } 774fn main() { let foo: Foo = Q$0 }
780"#, 775"#,
781 expect![[r#" 776 expect![[r#"
782 ev Foo::Bar () 777 ev Foo::Bar ()
@@ -793,7 +788,7 @@ fn main() { let foo: Foo = Q<|> }
793 check( 788 check(
794 r#" 789 r#"
795mod m { pub enum E { V } } 790mod m { pub enum E { V } }
796fn f() -> m::E { V<|> } 791fn f() -> m::E { V$0 }
797"#, 792"#,
798 expect![[r#" 793 expect![[r#"
799 ev m::E::V () 794 ev m::E::V ()
@@ -808,7 +803,7 @@ fn f() -> m::E { V<|> }
808 check( 803 check(
809 r#" 804 r#"
810struct Foo; 805struct Foo;
811#[<|>] 806#[$0]
812fn f() {} 807fn f() {}
813"#, 808"#,
814 expect![[""]], 809 expect![[""]],
@@ -822,7 +817,7 @@ fn f() {}
822trait MyTrait {} 817trait MyTrait {}
823struct MyStruct {} 818struct MyStruct {}
824 819
825impl My<|> 820impl My$0
826"#, 821"#,
827 expect![[r#" 822 expect![[r#"
828 tp Self 823 tp Self
@@ -835,7 +830,7 @@ impl My<|>
835 #[test] 830 #[test]
836 fn function_fuzzy_completion() { 831 fn function_fuzzy_completion() {
837 check_edit_with_config( 832 check_edit_with_config(
838 fuzzy_completion_config(), 833 TEST_CONFIG,
839 "stdin", 834 "stdin",
840 r#" 835 r#"
841//- /lib.rs crate:dep 836//- /lib.rs crate:dep
@@ -845,7 +840,7 @@ pub mod io {
845 840
846//- /main.rs crate:main deps:dep 841//- /main.rs crate:main deps:dep
847fn main() { 842fn main() {
848 stdi<|> 843 stdi$0
849} 844}
850"#, 845"#,
851 r#" 846 r#"
@@ -861,7 +856,7 @@ fn main() {
861 #[test] 856 #[test]
862 fn macro_fuzzy_completion() { 857 fn macro_fuzzy_completion() {
863 check_edit_with_config( 858 check_edit_with_config(
864 fuzzy_completion_config(), 859 TEST_CONFIG,
865 "macro_with_curlies!", 860 "macro_with_curlies!",
866 r#" 861 r#"
867//- /lib.rs crate:dep 862//- /lib.rs crate:dep
@@ -873,7 +868,7 @@ macro_rules! macro_with_curlies {
873 868
874//- /main.rs crate:main deps:dep 869//- /main.rs crate:main deps:dep
875fn main() { 870fn main() {
876 curli<|> 871 curli$0
877} 872}
878"#, 873"#,
879 r#" 874 r#"
@@ -889,7 +884,7 @@ fn main() {
889 #[test] 884 #[test]
890 fn struct_fuzzy_completion() { 885 fn struct_fuzzy_completion() {
891 check_edit_with_config( 886 check_edit_with_config(
892 fuzzy_completion_config(), 887 TEST_CONFIG,
893 "ThirdStruct", 888 "ThirdStruct",
894 r#" 889 r#"
895//- /lib.rs crate:dep 890//- /lib.rs crate:dep
@@ -903,7 +898,7 @@ pub mod some_module {
903use dep::{FirstStruct, some_module::SecondStruct}; 898use dep::{FirstStruct, some_module::SecondStruct};
904 899
905fn main() { 900fn main() {
906 this<|> 901 this$0
907} 902}
908"#, 903"#,
909 r#" 904 r#"
@@ -920,7 +915,7 @@ fn main() {
920 fn fuzzy_completions_come_in_specific_order() { 915 fn fuzzy_completions_come_in_specific_order() {
921 mark::check!(certain_fuzzy_order_test); 916 mark::check!(certain_fuzzy_order_test);
922 check_with_config( 917 check_with_config(
923 fuzzy_completion_config(), 918 TEST_CONFIG,
924 r#" 919 r#"
925//- /lib.rs crate:dep 920//- /lib.rs crate:dep
926pub struct FirstStruct; 921pub struct FirstStruct;
@@ -941,7 +936,7 @@ pub mod some_module {
941use dep::{FirstStruct, some_module::SecondStruct}; 936use dep::{FirstStruct, some_module::SecondStruct};
942 937
943fn main() { 938fn main() {
944 hir<|> 939 hir$0
945} 940}
946"#, 941"#,
947 expect![[r#" 942 expect![[r#"
diff --git a/crates/completion/src/config.rs b/crates/completion/src/config.rs
index 30577dc11..b4439b7d1 100644
--- a/crates/completion/src/config.rs
+++ b/crates/completion/src/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//! 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};
8use rustc_hash::FxHashSet;
9 8
10#[derive(Clone, Debug, PartialEq, Eq)] 9#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct CompletionConfig { 10pub struct CompletionConfig {
@@ -15,49 +14,4 @@ pub struct CompletionConfig {
15 pub add_call_argument_snippets: bool, 14 pub add_call_argument_snippets: bool,
16 pub snippet_cap: Option<SnippetCap>, 15 pub snippet_cap: Option<SnippetCap>,
17 pub merge: Option<MergeBehavior>, 16 pub merge: Option<MergeBehavior>,
18 /// A set of capabilities, enabled on the client and supported on the server.
19 pub active_resolve_capabilities: FxHashSet<CompletionResolveCapability>,
20}
21
22/// A resolve capability, supported on the server.
23/// If the client registers any completion resolve capabilities,
24/// the server is able to render completion items' corresponding fields later,
25/// not during an initial completion item request.
26/// See https://github.com/rust-analyzer/rust-analyzer/issues/6366 for more details.
27#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
28pub enum CompletionResolveCapability {
29 Documentation,
30 Detail,
31 AdditionalTextEdits,
32}
33
34impl CompletionConfig {
35 pub fn allow_snippets(&mut self, yes: bool) {
36 self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None }
37 }
38
39 /// Whether the completions' additional edits are calculated when sending an initional completions list
40 /// or later, in a separate resolve request.
41 pub fn resolve_additional_edits_lazily(&self) -> bool {
42 self.active_resolve_capabilities.contains(&CompletionResolveCapability::AdditionalTextEdits)
43 }
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub struct SnippetCap {
48 _private: (),
49}
50
51impl Default for CompletionConfig {
52 fn default() -> Self {
53 CompletionConfig {
54 enable_postfix_completions: true,
55 enable_autoimport_completions: true,
56 add_call_parenthesis: true,
57 add_call_argument_snippets: true,
58 snippet_cap: Some(SnippetCap { _private: () }),
59 merge: Some(MergeBehavior::Full),
60 active_resolve_capabilities: FxHashSet::default(),
61 }
62 }
63} 17}
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs
index 41de324d8..ebf28e887 100644
--- a/crates/completion/src/context.rs
+++ b/crates/completion/src/context.rs
@@ -63,7 +63,7 @@ pub(crate) struct CompletionContext<'a> {
63 pub(super) is_expr: bool, 63 pub(super) is_expr: bool,
64 /// Something is typed at the "top" level, in module or impl/trait. 64 /// Something is typed at the "top" level, in module or impl/trait.
65 pub(super) is_new_item: bool, 65 pub(super) is_new_item: bool,
66 /// The receiver if this is a field or method access, i.e. writing something.<|> 66 /// The receiver if this is a field or method access, i.e. writing something.$0
67 pub(super) dot_receiver: Option<ast::Expr>, 67 pub(super) dot_receiver: Option<ast::Expr>,
68 pub(super) dot_receiver_is_ambiguous_float_literal: bool, 68 pub(super) dot_receiver_is_ambiguous_float_literal: bool,
69 /// If this is a call (method or function) in particular, i.e. the () are already there. 69 /// If this is a call (method or function) in particular, i.e. the () are already there.
@@ -228,9 +228,9 @@ impl<'a> CompletionContext<'a> {
228 228
229 /// Checks whether completions in that particular case don't make much sense. 229 /// Checks whether completions in that particular case don't make much sense.
230 /// Examples: 230 /// Examples:
231 /// - `fn <|>` -- we expect function name, it's unlikely that "hint" will be helpful. 231 /// - `fn $0` -- we expect function name, it's unlikely that "hint" will be helpful.
232 /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names. 232 /// Exception for this case is `impl Trait for Foo`, where we would like to hint trait method names.
233 /// - `for _ i<|>` -- obviously, it'll be "in" keyword. 233 /// - `for _ i$0` -- obviously, it'll be "in" keyword.
234 pub(crate) fn no_completion_required(&self) -> bool { 234 pub(crate) fn no_completion_required(&self) -> bool {
235 (self.fn_is_prev && !self.inside_impl_trait_block) || self.for_is_prev2 235 (self.fn_is_prev && !self.inside_impl_trait_block) || self.for_is_prev2
236 } 236 }
@@ -279,7 +279,7 @@ impl<'a> CompletionContext<'a> {
279 offset: TextSize, 279 offset: TextSize,
280 ) { 280 ) {
281 // FIXME: this is wrong in at least two cases: 281 // FIXME: this is wrong in at least two cases:
282 // * when there's no token `foo(<|>)` 282 // * when there's no token `foo($0)`
283 // * when there is a token, but it happens to have type of it's own 283 // * when there is a token, but it happens to have type of it's own
284 self.expected_type = self 284 self.expected_type = self
285 .token 285 .token
@@ -458,7 +458,7 @@ impl<'a> CompletionContext<'a> {
458 } 458 }
459 if let Some(block) = ast::BlockExpr::cast(node) { 459 if let Some(block) = ast::BlockExpr::cast(node) {
460 return Some( 460 return Some(
461 block.expr().map(|e| e.syntax().text_range()) 461 block.tail_expr().map(|e| e.syntax().text_range())
462 == Some(name_ref.syntax().text_range()), 462 == Some(name_ref.syntax().text_range()),
463 ); 463 );
464 } 464 }
diff --git a/crates/completion/src/item.rs b/crates/completion/src/item.rs
index 65f8353e7..35af354b0 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.
@@ -45,7 +43,7 @@ pub struct CompletionItem {
45 /// Lookup is used to check if completion item indeed can complete current 43 /// Lookup is used to check if completion item indeed can complete current
46 /// ident. 44 /// ident.
47 /// 45 ///
48 /// That is, in `foo.bar<|>` lookup of `abracadabra` will be accepted (it 46 /// That is, in `foo.bar$0` lookup of `abracadabra` will be accepted (it
49 /// contains `bar` sub sequence), and `quux` will rejected. 47 /// contains `bar` sub sequence), and `quux` will rejected.
50 lookup: Option<String>, 48 lookup: Option<String>,
51 49
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index c57d05bbe..6cba88a6b 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -20,7 +20,7 @@ use text_edit::TextEdit;
20use crate::{completions::Completions, context::CompletionContext, item::CompletionKind}; 20use crate::{completions::Completions, context::CompletionContext, item::CompletionKind};
21 21
22pub use crate::{ 22pub use crate::{
23 config::{CompletionConfig, CompletionResolveCapability}, 23 config::CompletionConfig,
24 item::{CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat}, 24 item::{CompletionItem, CompletionItemKind, CompletionScore, ImportEdit, InsertTextFormat},
25}; 25};
26 26
@@ -47,8 +47,8 @@ pub use crate::{
47// - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result` 47// - `expr.while` -> `while expr {}` or `while let ... {}` for `Option` or `Result`
48// - `expr.ref` -> `&expr` 48// - `expr.ref` -> `&expr`
49// - `expr.refm` -> `&mut expr` 49// - `expr.refm` -> `&mut expr`
50// - `expr.let` -> `let <|> = expr;` 50// - `expr.let` -> `let $0 = expr;`
51// - `expr.letm` -> `let mut <|> = expr;` 51// - `expr.letm` -> `let mut $0 = expr;`
52// - `expr.not` -> `!expr` 52// - `expr.not` -> `!expr`
53// - `expr.dbg` -> `dbg!(expr)` 53// - `expr.dbg` -> `dbg!(expr)`
54// - `expr.dbgr` -> `dbg!(&expr)` 54// - `expr.dbgr` -> `dbg!(&expr)`
@@ -92,7 +92,7 @@ pub use crate::{
92/// ```no_run 92/// ```no_run
93/// fn f() { 93/// fn f() {
94/// let foo = 92; 94/// let foo = 92;
95/// let _ = bar<|> 95/// let _ = bar$0
96/// } 96/// }
97/// ``` 97/// ```
98/// 98///
@@ -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| {
@@ -221,7 +220,7 @@ mod tests {
221 220
222 fn foo() { 221 fn foo() {
223 let bar = Bar; 222 let bar = Bar;
224 bar.fo<|>; 223 bar.fo$0;
225 } 224 }
226 "#, 225 "#,
227 DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" }, 226 DetailAndDocumentation { detail: "fn foo(&self)", documentation: "Do the foo" },
@@ -247,7 +246,7 @@ mod tests {
247 246
248 fn foo() { 247 fn foo() {
249 let bar = Bar; 248 let bar = Bar;
250 bar.fo<|>; 249 bar.fo$0;
251 } 250 }
252 "#, 251 "#,
253 DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" }, 252 DetailAndDocumentation { detail: "fn foo(&self)", documentation: " Do the foo" },
@@ -260,7 +259,7 @@ mod tests {
260 check_no_completion( 259 check_no_completion(
261 r#" 260 r#"
262 fn foo() { 261 fn foo() {
263 for i i<|> 262 for i i$0
264 } 263 }
265 "#, 264 "#,
266 ); 265 );
@@ -271,7 +270,7 @@ mod tests {
271 fn foo() -> &'static str { "foo" } 270 fn foo() -> &'static str { "foo" }
272 271
273 fn bar() { 272 fn bar() {
274 for c in fo<|> 273 for c in fo$0
275 } 274 }
276 "#, 275 "#,
277 DetailAndDocumentation { 276 DetailAndDocumentation {
diff --git a/crates/completion/src/patterns.rs b/crates/completion/src/patterns.rs
index b0f35f9bf..f3ce91dd1 100644
--- a/crates/completion/src/patterns.rs
+++ b/crates/completion/src/patterns.rs
@@ -5,7 +5,7 @@ use syntax::{
5 ast::{self, LoopBodyOwner}, 5 ast::{self, LoopBodyOwner},
6 match_ast, AstNode, Direction, NodeOrToken, SyntaxElement, 6 match_ast, AstNode, Direction, NodeOrToken, SyntaxElement,
7 SyntaxKind::*, 7 SyntaxKind::*,
8 SyntaxNode, SyntaxToken, 8 SyntaxNode, SyntaxToken, T,
9}; 9};
10 10
11#[cfg(test)] 11#[cfg(test)]
@@ -20,7 +20,7 @@ pub(crate) fn has_trait_parent(element: SyntaxElement) -> bool {
20} 20}
21#[test] 21#[test]
22fn test_has_trait_parent() { 22fn test_has_trait_parent() {
23 check_pattern_is_applicable(r"trait A { f<|> }", has_trait_parent); 23 check_pattern_is_applicable(r"trait A { f$0 }", has_trait_parent);
24} 24}
25 25
26pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool { 26pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
@@ -32,7 +32,7 @@ pub(crate) fn has_impl_parent(element: SyntaxElement) -> bool {
32} 32}
33#[test] 33#[test]
34fn test_has_impl_parent() { 34fn test_has_impl_parent() {
35 check_pattern_is_applicable(r"impl A { f<|> }", has_impl_parent); 35 check_pattern_is_applicable(r"impl A { f$0 }", has_impl_parent);
36} 36}
37 37
38pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool { 38pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
@@ -47,10 +47,10 @@ pub(crate) fn inside_impl_trait_block(element: SyntaxElement) -> bool {
47} 47}
48#[test] 48#[test]
49fn test_inside_impl_trait_block() { 49fn test_inside_impl_trait_block() {
50 check_pattern_is_applicable(r"impl Foo for Bar { f<|> }", inside_impl_trait_block); 50 check_pattern_is_applicable(r"impl Foo for Bar { f$0 }", inside_impl_trait_block);
51 check_pattern_is_applicable(r"impl Foo for Bar { fn f<|> }", inside_impl_trait_block); 51 check_pattern_is_applicable(r"impl Foo for Bar { fn f$0 }", inside_impl_trait_block);
52 check_pattern_is_not_applicable(r"impl A { f<|> }", inside_impl_trait_block); 52 check_pattern_is_not_applicable(r"impl A { f$0 }", inside_impl_trait_block);
53 check_pattern_is_not_applicable(r"impl A { fn f<|> }", inside_impl_trait_block); 53 check_pattern_is_not_applicable(r"impl A { fn f$0 }", inside_impl_trait_block);
54} 54}
55 55
56pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool { 56pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
@@ -58,8 +58,8 @@ pub(crate) fn has_field_list_parent(element: SyntaxElement) -> bool {
58} 58}
59#[test] 59#[test]
60fn test_has_field_list_parent() { 60fn test_has_field_list_parent() {
61 check_pattern_is_applicable(r"struct Foo { f<|> }", has_field_list_parent); 61 check_pattern_is_applicable(r"struct Foo { f$0 }", has_field_list_parent);
62 check_pattern_is_applicable(r"struct Foo { f<|> pub f: i32}", has_field_list_parent); 62 check_pattern_is_applicable(r"struct Foo { f$0 pub f: i32}", has_field_list_parent);
63} 63}
64 64
65pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool { 65pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool {
@@ -67,7 +67,7 @@ pub(crate) fn has_block_expr_parent(element: SyntaxElement) -> bool {
67} 67}
68#[test] 68#[test]
69fn test_has_block_expr_parent() { 69fn test_has_block_expr_parent() {
70 check_pattern_is_applicable(r"fn my_fn() { let a = 2; f<|> }", has_block_expr_parent); 70 check_pattern_is_applicable(r"fn my_fn() { let a = 2; f$0 }", has_block_expr_parent);
71} 71}
72 72
73pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool { 73pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool {
@@ -75,8 +75,8 @@ pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool {
75} 75}
76#[test] 76#[test]
77fn test_has_bind_pat_parent() { 77fn test_has_bind_pat_parent() {
78 check_pattern_is_applicable(r"fn my_fn(m<|>) {}", has_bind_pat_parent); 78 check_pattern_is_applicable(r"fn my_fn(m$0) {}", has_bind_pat_parent);
79 check_pattern_is_applicable(r"fn my_fn() { let m<|> }", has_bind_pat_parent); 79 check_pattern_is_applicable(r"fn my_fn() { let m$0 }", has_bind_pat_parent);
80} 80}
81 81
82pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool { 82pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool {
@@ -86,8 +86,8 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool {
86} 86}
87#[test] 87#[test]
88fn test_has_ref_parent() { 88fn test_has_ref_parent() {
89 check_pattern_is_applicable(r"fn my_fn(&m<|>) {}", has_ref_parent); 89 check_pattern_is_applicable(r"fn my_fn(&m$0) {}", has_ref_parent);
90 check_pattern_is_applicable(r"fn my() { let &m<|> }", has_ref_parent); 90 check_pattern_is_applicable(r"fn my() { let &m$0 }", has_ref_parent);
91} 91}
92 92
93pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool { 93pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool {
@@ -99,8 +99,8 @@ pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> boo
99} 99}
100#[test] 100#[test]
101fn test_has_item_list_or_source_file_parent() { 101fn test_has_item_list_or_source_file_parent() {
102 check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent); 102 check_pattern_is_applicable(r"i$0", has_item_list_or_source_file_parent);
103 check_pattern_is_applicable(r"mod foo { f<|> }", has_item_list_or_source_file_parent); 103 check_pattern_is_applicable(r"mod foo { f$0 }", has_item_list_or_source_file_parent);
104} 104}
105 105
106pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { 106pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
@@ -112,26 +112,26 @@ pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
112} 112}
113#[test] 113#[test]
114fn test_is_match_arm() { 114fn test_is_match_arm() {
115 check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); 115 check_pattern_is_applicable(r"fn my_fn() { match () { () => m$0 } }", is_match_arm);
116} 116}
117 117
118pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool { 118pub(crate) fn unsafe_is_prev(element: SyntaxElement) -> bool {
119 element 119 element
120 .into_token() 120 .into_token()
121 .and_then(|it| previous_non_trivia_token(it)) 121 .and_then(|it| previous_non_trivia_token(it))
122 .filter(|it| it.kind() == UNSAFE_KW) 122 .filter(|it| it.kind() == T![unsafe])
123 .is_some() 123 .is_some()
124} 124}
125#[test] 125#[test]
126fn test_unsafe_is_prev() { 126fn test_unsafe_is_prev() {
127 check_pattern_is_applicable(r"unsafe i<|>", unsafe_is_prev); 127 check_pattern_is_applicable(r"unsafe i$0", unsafe_is_prev);
128} 128}
129 129
130pub(crate) fn if_is_prev(element: SyntaxElement) -> bool { 130pub(crate) fn if_is_prev(element: SyntaxElement) -> bool {
131 element 131 element
132 .into_token() 132 .into_token()
133 .and_then(|it| previous_non_trivia_token(it)) 133 .and_then(|it| previous_non_trivia_token(it))
134 .filter(|it| it.kind() == IF_KW) 134 .filter(|it| it.kind() == T![if])
135 .is_some() 135 .is_some()
136} 136}
137 137
@@ -139,32 +139,32 @@ pub(crate) fn fn_is_prev(element: SyntaxElement) -> bool {
139 element 139 element
140 .into_token() 140 .into_token()
141 .and_then(|it| previous_non_trivia_token(it)) 141 .and_then(|it| previous_non_trivia_token(it))
142 .filter(|it| it.kind() == FN_KW) 142 .filter(|it| it.kind() == T![fn])
143 .is_some() 143 .is_some()
144} 144}
145#[test] 145#[test]
146fn test_fn_is_prev() { 146fn test_fn_is_prev() {
147 check_pattern_is_applicable(r"fn l<|>", fn_is_prev); 147 check_pattern_is_applicable(r"fn l$0", fn_is_prev);
148} 148}
149 149
150/// Check if the token previous to the previous one is `for`. 150/// Check if the token previous to the previous one is `for`.
151/// For example, `for _ i<|>` => true. 151/// For example, `for _ i$0` => true.
152pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool { 152pub(crate) fn for_is_prev2(element: SyntaxElement) -> bool {
153 element 153 element
154 .into_token() 154 .into_token()
155 .and_then(|it| previous_non_trivia_token(it)) 155 .and_then(|it| previous_non_trivia_token(it))
156 .and_then(|it| previous_non_trivia_token(it)) 156 .and_then(|it| previous_non_trivia_token(it))
157 .filter(|it| it.kind() == FOR_KW) 157 .filter(|it| it.kind() == T![for])
158 .is_some() 158 .is_some()
159} 159}
160#[test] 160#[test]
161fn test_for_is_prev2() { 161fn test_for_is_prev2() {
162 check_pattern_is_applicable(r"for i i<|>", for_is_prev2); 162 check_pattern_is_applicable(r"for i i$0", for_is_prev2);
163} 163}
164 164
165#[test] 165#[test]
166fn test_if_is_prev() { 166fn test_if_is_prev() {
167 check_pattern_is_applicable(r"if l<|>", if_is_prev); 167 check_pattern_is_applicable(r"if l$0", if_is_prev);
168} 168}
169 169
170pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool { 170pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool {
@@ -172,7 +172,7 @@ pub(crate) fn has_trait_as_prev_sibling(element: SyntaxElement) -> bool {
172} 172}
173#[test] 173#[test]
174fn test_has_trait_as_prev_sibling() { 174fn test_has_trait_as_prev_sibling() {
175 check_pattern_is_applicable(r"trait A w<|> {}", has_trait_as_prev_sibling); 175 check_pattern_is_applicable(r"trait A w$0 {}", has_trait_as_prev_sibling);
176} 176}
177 177
178pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool { 178pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool {
@@ -180,7 +180,7 @@ pub(crate) fn has_impl_as_prev_sibling(element: SyntaxElement) -> bool {
180} 180}
181#[test] 181#[test]
182fn test_has_impl_as_prev_sibling() { 182fn test_has_impl_as_prev_sibling() {
183 check_pattern_is_applicable(r"impl A w<|> {}", has_impl_as_prev_sibling); 183 check_pattern_is_applicable(r"impl A w$0 {}", has_impl_as_prev_sibling);
184} 184}
185 185
186pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool { 186pub(crate) fn is_in_loop_body(element: SyntaxElement) -> bool {
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index 1ba7201a1..e93c59f71 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};
@@ -157,8 +157,7 @@ impl<'a> Render<'a> {
157 157
158 let kind = match resolution { 158 let kind = match resolution {
159 ScopeDef::ModuleDef(Function(func)) => { 159 ScopeDef::ModuleDef(Function(func)) => {
160 let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); 160 return render_fn(self.ctx, import_to_add, Some(local_name), *func);
161 return Some(item);
162 } 161 }
163 ScopeDef::ModuleDef(Variant(_)) 162 ScopeDef::ModuleDef(Variant(_))
164 if self.ctx.completion.is_pat_binding_or_const 163 if self.ctx.completion.is_pat_binding_or_const
@@ -321,8 +320,8 @@ mod tests {
321 use test_utils::mark; 320 use test_utils::mark;
322 321
323 use crate::{ 322 use crate::{
324 test_utils::{check_edit, do_completion, get_all_items}, 323 test_utils::{check_edit, do_completion, get_all_items, TEST_CONFIG},
325 CompletionConfig, CompletionKind, CompletionScore, 324 CompletionKind, CompletionScore,
326 }; 325 };
327 326
328 fn check(ra_fixture: &str, expect: Expect) { 327 fn check(ra_fixture: &str, expect: Expect) {
@@ -339,7 +338,7 @@ mod tests {
339 } 338 }
340 } 339 }
341 340
342 let mut completions = get_all_items(CompletionConfig::default(), ra_fixture); 341 let mut completions = get_all_items(TEST_CONFIG, ra_fixture);
343 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()));
344 let actual = completions 343 let actual = completions
345 .into_iter() 344 .into_iter()
@@ -359,7 +358,7 @@ mod tests {
359 r#" 358 r#"
360enum Foo { Foo { x: i32, y: i32 } } 359enum Foo { Foo { x: i32, y: i32 } }
361 360
362fn main() { Foo::Fo<|> } 361fn main() { Foo::Fo$0 }
363"#, 362"#,
364 expect![[r#" 363 expect![[r#"
365 [ 364 [
@@ -382,7 +381,7 @@ fn main() { Foo::Fo<|> }
382 r#" 381 r#"
383enum Foo { Foo (i32, i32) } 382enum Foo { Foo (i32, i32) }
384 383
385fn main() { Foo::Fo<|> } 384fn main() { Foo::Fo$0 }
386"#, 385"#,
387 expect![[r#" 386 expect![[r#"
388 [ 387 [
@@ -407,7 +406,7 @@ fn main() { Foo::Fo<|> }
407 r#" 406 r#"
408enum Foo { Foo } 407enum Foo { Foo }
409 408
410fn main() { Foo::Fo<|> } 409fn main() { Foo::Fo$0 }
411"#, 410"#,
412 expect![[r#" 411 expect![[r#"
413 [ 412 [
@@ -431,7 +430,7 @@ fn main() { Foo::Fo<|> }
431mod m { 430mod m {
432 pub enum Spam { Foo, Bar(i32) } 431 pub enum Spam { Foo, Bar(i32) }
433} 432}
434fn main() { let _: m::Spam = S<|> } 433fn main() { let _: m::Spam = S$0 }
435"#, 434"#,
436 expect![[r#" 435 expect![[r#"
437 [ 436 [
@@ -484,7 +483,7 @@ fn something_deprecated() {}
484#[deprecated(since = "1.0.0")] 483#[deprecated(since = "1.0.0")]
485fn something_else_deprecated() {} 484fn something_else_deprecated() {}
486 485
487fn main() { som<|> } 486fn main() { som$0 }
488"#, 487"#,
489 expect![[r#" 488 expect![[r#"
490 [ 489 [
@@ -524,7 +523,7 @@ fn main() { som<|> }
524 check( 523 check(
525 r#" 524 r#"
526struct A { #[deprecated] the_field: u32 } 525struct A { #[deprecated] the_field: u32 }
527fn foo() { A { the<|> } } 526fn foo() { A { the$0 } }
528"#, 527"#,
529 expect![[r#" 528 expect![[r#"
530 [ 529 [
@@ -552,7 +551,7 @@ struct S {
552} 551}
553impl S { 552impl S {
554 /// Method docs 553 /// Method docs
555 fn bar(self) { self.<|> } 554 fn bar(self) { self.$0 }
556}"#, 555}"#,
557 expect![[r#" 556 expect![[r#"
558 [ 557 [
@@ -585,7 +584,7 @@ impl S {
585 584
586 check( 585 check(
587 r#" 586 r#"
588use self::my<|>; 587use self::my$0;
589 588
590/// mod docs 589/// mod docs
591mod my { } 590mod my { }
@@ -644,7 +643,7 @@ impl S {
644 #[inline] 643 #[inline]
645 fn the_method(&self) { } 644 fn the_method(&self) { }
646} 645}
647fn foo(s: S) { s.<|> } 646fn foo(s: S) { s.$0 }
648"#, 647"#,
649 expect![[r#" 648 expect![[r#"
650 [ 649 [
@@ -672,7 +671,7 @@ fn foo(foo: u8, bar: u8) {}
672struct ManualVtable { f: fn(u8, u8) } 671struct ManualVtable { f: fn(u8, u8) }
673 672
674fn main() -> ManualVtable { 673fn main() -> ManualVtable {
675 ManualVtable { f: f<|> } 674 ManualVtable { f: f$0 }
676} 675}
677"#, 676"#,
678 r#" 677 r#"
@@ -693,7 +692,7 @@ fn main() -> ManualVtable {
693 "foo", 692 "foo",
694 r#" 693 r#"
695mod m { pub fn foo() {} } 694mod m { pub fn foo() {} }
696use crate::m::f<|>; 695use crate::m::f$0;
697"#, 696"#,
698 r#" 697 r#"
699mod m { pub fn foo() {} } 698mod m { pub fn foo() {} }
@@ -708,7 +707,7 @@ use crate::m::foo;
708 "foo", 707 "foo",
709 r#" 708 r#"
710fn foo(x: i32) {} 709fn foo(x: i32) {}
711fn main() { f<|>(); } 710fn main() { f$0(); }
712"#, 711"#,
713 r#" 712 r#"
714fn foo(x: i32) {} 713fn foo(x: i32) {}
@@ -720,7 +719,7 @@ fn main() { foo(); }
720 r#" 719 r#"
721struct Foo; 720struct Foo;
722impl Foo { fn foo(&self){} } 721impl Foo { fn foo(&self){} }
723fn f(foo: &Foo) { foo.f<|>(); } 722fn f(foo: &Foo) { foo.f$0(); }
724"#, 723"#,
725 r#" 724 r#"
726struct Foo; 725struct Foo;
@@ -737,7 +736,7 @@ fn f(foo: &Foo) { foo.foo(); }
737 "Vec", 736 "Vec",
738 r#" 737 r#"
739struct Vec<T> {} 738struct Vec<T> {}
740fn foo(xs: Ve<|>) 739fn foo(xs: Ve$0)
741"#, 740"#,
742 r#" 741 r#"
743struct Vec<T> {} 742struct Vec<T> {}
@@ -748,7 +747,7 @@ fn foo(xs: Vec<$0>)
748 "Vec", 747 "Vec",
749 r#" 748 r#"
750type Vec<T> = (T,); 749type Vec<T> = (T,);
751fn foo(xs: Ve<|>) 750fn foo(xs: Ve$0)
752"#, 751"#,
753 r#" 752 r#"
754type Vec<T> = (T,); 753type Vec<T> = (T,);
@@ -759,7 +758,7 @@ fn foo(xs: Vec<$0>)
759 "Vec", 758 "Vec",
760 r#" 759 r#"
761struct Vec<T = i128> {} 760struct Vec<T = i128> {}
762fn foo(xs: Ve<|>) 761fn foo(xs: Ve$0)
763"#, 762"#,
764 r#" 763 r#"
765struct Vec<T = i128> {} 764struct Vec<T = i128> {}
@@ -770,7 +769,7 @@ fn foo(xs: Vec)
770 "Vec", 769 "Vec",
771 r#" 770 r#"
772struct Vec<T> {} 771struct Vec<T> {}
773fn foo(xs: Ve<|><i128>) 772fn foo(xs: Ve$0<i128>)
774"#, 773"#,
775 r#" 774 r#"
776struct Vec<T> {} 775struct Vec<T> {}
@@ -786,7 +785,7 @@ fn foo(xs: Vec<i128>)
786 r#" 785 r#"
787struct S { foo: i64, bar: u32, baz: u32 } 786struct S { foo: i64, bar: u32, baz: u32 }
788fn test(bar: u32) { } 787fn test(bar: u32) { }
789fn foo(s: S) { test(s.<|>) } 788fn foo(s: S) { test(s.$0) }
790"#, 789"#,
791 expect![[r#" 790 expect![[r#"
792 fd bar [type+name] 791 fd bar [type+name]
@@ -803,7 +802,7 @@ fn foo(s: S) { test(s.<|>) }
803 r#" 802 r#"
804struct A { foo: i64, bar: u32, baz: u32 } 803struct A { foo: i64, bar: u32, baz: u32 }
805struct B { x: (), y: f32, bar: u32 } 804struct B { x: (), y: f32, bar: u32 }
806fn foo(a: A) { B { bar: a.<|> }; } 805fn foo(a: A) { B { bar: a.$0 }; }
807"#, 806"#,
808 expect![[r#" 807 expect![[r#"
809 fd bar [type+name] 808 fd bar [type+name]
@@ -820,7 +819,7 @@ fn foo(a: A) { B { bar: a.<|> }; }
820struct A { foo: i64, bar: u32, baz: u32 } 819struct A { foo: i64, bar: u32, baz: u32 }
821struct B { x: (), y: f32, bar: u32 } 820struct B { x: (), y: f32, bar: u32 }
822fn f(foo: i64) { } 821fn f(foo: i64) { }
823fn foo(a: A) { B { bar: f(a.<|>) }; } 822fn foo(a: A) { B { bar: f(a.$0) }; }
824"#, 823"#,
825 expect![[r#" 824 expect![[r#"
826 fd foo [type+name] 825 fd foo [type+name]
@@ -833,7 +832,7 @@ fn foo(a: A) { B { bar: f(a.<|>) }; }
833struct A { foo: i64, bar: u32, baz: u32 } 832struct A { foo: i64, bar: u32, baz: u32 }
834struct B { x: (), y: f32, bar: u32 } 833struct B { x: (), y: f32, bar: u32 }
835fn f(foo: i64) { } 834fn f(foo: i64) { }
836fn foo(a: A) { f(B { bar: a.<|> }); } 835fn foo(a: A) { f(B { bar: a.$0 }); }
837"#, 836"#,
838 expect![[r#" 837 expect![[r#"
839 fd bar [type+name] 838 fd bar [type+name]
@@ -848,7 +847,7 @@ fn foo(a: A) { f(B { bar: a.<|> }); }
848 check_scores( 847 check_scores(
849 r#" 848 r#"
850struct WorldSnapshot { _f: () }; 849struct WorldSnapshot { _f: () };
851fn go(world: &WorldSnapshot) { go(w<|>) } 850fn go(world: &WorldSnapshot) { go(w$0) }
852"#, 851"#,
853 expect![[r#" 852 expect![[r#"
854 bn world [type+name] 853 bn world [type+name]
@@ -863,7 +862,7 @@ fn go(world: &WorldSnapshot) { go(w<|>) }
863 check_scores( 862 check_scores(
864 r#" 863 r#"
865struct Foo; 864struct Foo;
866fn f(foo: &Foo) { f(foo, w<|>) } 865fn f(foo: &Foo) { f(foo, w$0) }
867"#, 866"#,
868 expect![[r#" 867 expect![[r#"
869 st Foo [] 868 st Foo []
diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs
index 039bdabc0..ce924f309 100644
--- a/crates/completion/src/render/const_.rs
+++ b/crates/completion/src/render/const_.rs
@@ -15,7 +15,7 @@ pub(crate) fn render_const<'a>(
15 ctx: RenderContext<'a>, 15 ctx: RenderContext<'a>,
16 const_: hir::Const, 16 const_: hir::Const,
17) -> Option<CompletionItem> { 17) -> Option<CompletionItem> {
18 ConstRender::new(ctx, const_).render() 18 ConstRender::new(ctx, const_)?.render()
19} 19}
20 20
21#[derive(Debug)] 21#[derive(Debug)]
@@ -26,9 +26,9 @@ struct ConstRender<'a> {
26} 26}
27 27
28impl<'a> ConstRender<'a> { 28impl<'a> ConstRender<'a> {
29 fn new(ctx: RenderContext<'a>, const_: hir::Const) -> ConstRender<'a> { 29 fn new(ctx: RenderContext<'a>, const_: hir::Const) -> Option<ConstRender<'a>> {
30 let ast_node = const_.source(ctx.db()).value; 30 let ast_node = const_.source(ctx.db())?.value;
31 ConstRender { ctx, const_, ast_node } 31 Some(ConstRender { ctx, const_, ast_node })
32 } 32 }
33 33
34 fn render(self) -> Option<CompletionItem> { 34 fn render(self) -> Option<CompletionItem> {
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs
index 732e139ec..89fb49773 100644
--- a/crates/completion/src/render/enum_variant.rs
+++ b/crates/completion/src/render/enum_variant.rs
@@ -115,7 +115,7 @@ mod tests {
115enum Option<T> { Some(T), None } 115enum Option<T> { Some(T), None }
116use Option::*; 116use Option::*;
117fn main() -> Option<i32> { 117fn main() -> Option<i32> {
118 Som<|> 118 Som$0
119} 119}
120"#, 120"#,
121 r#" 121 r#"
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index 316e05b52..f5b0ce3e3 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -14,9 +14,9 @@ pub(crate) fn render_fn<'a>(
14 import_to_add: Option<ImportEdit>, 14 import_to_add: Option<ImportEdit>,
15 local_name: Option<String>, 15 local_name: Option<String>,
16 fn_: hir::Function, 16 fn_: hir::Function,
17) -> CompletionItem { 17) -> Option<CompletionItem> {
18 let _p = profile::span("render_fn"); 18 let _p = profile::span("render_fn");
19 FunctionRender::new(ctx, local_name, fn_).render(import_to_add) 19 Some(FunctionRender::new(ctx, local_name, fn_)?.render(import_to_add))
20} 20}
21 21
22#[derive(Debug)] 22#[derive(Debug)]
@@ -32,11 +32,11 @@ impl<'a> FunctionRender<'a> {
32 ctx: RenderContext<'a>, 32 ctx: RenderContext<'a>,
33 local_name: Option<String>, 33 local_name: Option<String>,
34 fn_: hir::Function, 34 fn_: hir::Function,
35 ) -> FunctionRender<'a> { 35 ) -> Option<FunctionRender<'a>> {
36 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string()); 36 let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string());
37 let ast_node = fn_.source(ctx.db()).value; 37 let ast_node = fn_.source(ctx.db())?.value;
38 38
39 FunctionRender { ctx, name, func: fn_, ast_node } 39 Some(FunctionRender { ctx, name, func: fn_, ast_node })
40 } 40 }
41 41
42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { 42 fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
@@ -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
@@ -124,7 +124,7 @@ mod tests {
124 "no_args", 124 "no_args",
125 r#" 125 r#"
126fn no_args() {} 126fn no_args() {}
127fn main() { no_<|> } 127fn main() { no_$0 }
128"#, 128"#,
129 r#" 129 r#"
130fn no_args() {} 130fn no_args() {}
@@ -136,7 +136,7 @@ fn main() { no_args()$0 }
136 "with_args", 136 "with_args",
137 r#" 137 r#"
138fn with_args(x: i32, y: String) {} 138fn with_args(x: i32, y: String) {}
139fn main() { with_<|> } 139fn main() { with_$0 }
140"#, 140"#,
141 r#" 141 r#"
142fn with_args(x: i32, y: String) {} 142fn with_args(x: i32, y: String) {}
@@ -151,7 +151,7 @@ struct S;
151impl S { 151impl S {
152 fn foo(&self) {} 152 fn foo(&self) {}
153} 153}
154fn bar(s: &S) { s.f<|> } 154fn bar(s: &S) { s.f$0 }
155"#, 155"#,
156 r#" 156 r#"
157struct S; 157struct S;
@@ -170,7 +170,7 @@ impl S {
170 fn foo(&self, x: i32) {} 170 fn foo(&self, x: i32) {}
171} 171}
172fn bar(s: &S) { 172fn bar(s: &S) {
173 s.f<|> 173 s.f$0
174} 174}
175"#, 175"#,
176 r#" 176 r#"
@@ -195,7 +195,7 @@ struct S;
195impl S { 195impl S {
196 fn foo(&self) {} 196 fn foo(&self) {}
197} 197}
198fn main() { S::f<|> } 198fn main() { S::f$0 }
199"#, 199"#,
200 r#" 200 r#"
201struct S; 201struct S;
@@ -211,11 +211,11 @@ 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) {}
218fn main() { with_<|> } 218fn main() { with_$0 }
219"#, 219"#,
220 r#" 220 r#"
221fn with_args(x: i32, y: String) {} 221fn with_args(x: i32, y: String) {}
@@ -230,7 +230,7 @@ fn main() { with_args($0) }
230 "foo", 230 "foo",
231 r#" 231 r#"
232fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} 232fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
233fn main() { f<|> } 233fn main() { f$0 }
234"#, 234"#,
235 r#" 235 r#"
236fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {} 236fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
@@ -248,7 +248,7 @@ struct Foo {}
248fn ref_arg(x: &Foo) {} 248fn ref_arg(x: &Foo) {}
249fn main() { 249fn main() {
250 let x = Foo {}; 250 let x = Foo {};
251 ref_ar<|> 251 ref_ar$0
252} 252}
253"#, 253"#,
254 r#" 254 r#"
@@ -271,7 +271,7 @@ struct Foo {}
271fn ref_arg(x: &mut Foo) {} 271fn ref_arg(x: &mut Foo) {}
272fn main() { 272fn main() {
273 let x = Foo {}; 273 let x = Foo {};
274 ref_ar<|> 274 ref_ar$0
275} 275}
276"#, 276"#,
277 r#" 277 r#"
@@ -299,7 +299,7 @@ impl Bar {
299fn main() { 299fn main() {
300 let x = Foo {}; 300 let x = Foo {};
301 let y = Bar {}; 301 let y = Bar {};
302 y.<|> 302 y.$0
303} 303}
304"#, 304"#,
305 r#" 305 r#"
@@ -326,7 +326,7 @@ fn main() {
326fn take_mutably(mut x: &i32) {} 326fn take_mutably(mut x: &i32) {}
327 327
328fn main() { 328fn main() {
329 take_m<|> 329 take_m$0
330} 330}
331"#, 331"#,
332 r#" 332 r#"
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs
index dac79592f..f893e420a 100644
--- a/crates/completion/src/render/macro_.rs
+++ b/crates/completion/src/render/macro_.rs
@@ -39,20 +39,13 @@ impl<'a> MacroRender<'a> {
39 } 39 }
40 40
41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { 41 fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
42 // FIXME: Currently proc-macro do not have ast-node,
43 // such that it does not have source
44 // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
45 if self.macro_.is_proc_macro() {
46 return None;
47 }
48
49 let mut builder = 42 let mut builder =
50 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) 43 CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label())
51 .kind(CompletionItemKind::Macro) 44 .kind(CompletionItemKind::Macro)
52 .set_documentation(self.docs.clone()) 45 .set_documentation(self.docs.clone())
53 .set_deprecated(self.ctx.is_deprecated(self.macro_)) 46 .set_deprecated(self.ctx.is_deprecated(self.macro_))
54 .add_import(import_to_add) 47 .add_import(import_to_add)
55 .detail(self.detail()); 48 .set_detail(self.detail());
56 49
57 let needs_bang = self.needs_bang(); 50 let needs_bang = self.needs_bang();
58 builder = match self.ctx.snippet_cap() { 51 builder = match self.ctx.snippet_cap() {
@@ -95,9 +88,9 @@ impl<'a> MacroRender<'a> {
95 format!("{}!", self.name) 88 format!("{}!", self.name)
96 } 89 }
97 90
98 fn detail(&self) -> String { 91 fn detail(&self) -> Option<String> {
99 let ast_node = self.macro_.source(self.ctx.db()).value; 92 let ast_node = self.macro_.source(self.ctx.db())?.value;
100 macro_label(&ast_node) 93 Some(macro_label(&ast_node))
101 } 94 }
102} 95}
103 96
@@ -142,7 +135,7 @@ mod tests {
142 "frobnicate!", 135 "frobnicate!",
143 r#" 136 r#"
144//- /main.rs crate:main deps:foo 137//- /main.rs crate:main deps:foo
145use foo::<|>; 138use foo::$0;
146//- /foo/lib.rs crate:foo 139//- /foo/lib.rs crate:foo
147#[macro_export] 140#[macro_export]
148macro_rules! frobnicate { () => () } 141macro_rules! frobnicate { () => () }
@@ -156,7 +149,7 @@ use foo::frobnicate;
156 "frobnicate!", 149 "frobnicate!",
157 r#" 150 r#"
158macro_rules! frobnicate { () => () } 151macro_rules! frobnicate { () => () }
159fn main() { frob<|>!(); } 152fn main() { frob$0!(); }
160"#, 153"#,
161 r#" 154 r#"
162macro_rules! frobnicate { () => () } 155macro_rules! frobnicate { () => () }
@@ -180,7 +173,7 @@ fn main() { frobnicate!(); }
180/// ``` 173/// ```
181macro_rules! vec { () => {} } 174macro_rules! vec { () => {} }
182 175
183fn fn main() { v<|> } 176fn fn main() { v$0 }
184"#, 177"#,
185 r#" 178 r#"
186/// Creates a [`Vec`] containing the arguments. 179/// Creates a [`Vec`] containing the arguments.
@@ -205,7 +198,7 @@ fn fn main() { vec![$0] }
205/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`, 198/// Don't call `fooo!()` `fooo!()`, or `_foo![]` `_foo![]`,
206/// call as `let _=foo! { hello world };` 199/// call as `let _=foo! { hello world };`
207macro_rules! foo { () => {} } 200macro_rules! foo { () => {} }
208fn main() { <|> } 201fn main() { $0 }
209"#, 202"#,
210 r#" 203 r#"
211/// Foo 204/// Foo
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/render/type_alias.rs b/crates/completion/src/render/type_alias.rs
index 9605c7fa9..69b445b9c 100644
--- a/crates/completion/src/render/type_alias.rs
+++ b/crates/completion/src/render/type_alias.rs
@@ -15,7 +15,7 @@ pub(crate) fn render_type_alias<'a>(
15 ctx: RenderContext<'a>, 15 ctx: RenderContext<'a>,
16 type_alias: hir::TypeAlias, 16 type_alias: hir::TypeAlias,
17) -> Option<CompletionItem> { 17) -> Option<CompletionItem> {
18 TypeAliasRender::new(ctx, type_alias).render() 18 TypeAliasRender::new(ctx, type_alias)?.render()
19} 19}
20 20
21#[derive(Debug)] 21#[derive(Debug)]
@@ -26,9 +26,9 @@ struct TypeAliasRender<'a> {
26} 26}
27 27
28impl<'a> TypeAliasRender<'a> { 28impl<'a> TypeAliasRender<'a> {
29 fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> TypeAliasRender<'a> { 29 fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option<TypeAliasRender<'a>> {
30 let ast_node = type_alias.source(ctx.db()).value; 30 let ast_node = type_alias.source(ctx.db())?.value;
31 TypeAliasRender { ctx, type_alias, ast_node } 31 Some(TypeAliasRender { ctx, type_alias, ast_node })
32 } 32 }
33 33
34 fn render(self) -> Option<CompletionItem> { 34 fn render(self) -> Option<CompletionItem> {
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index eb0c16f52..3f4b9d4ac 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,12 +13,21 @@ use test_utils::{assert_eq_text, RangeOrOffset};
10 13
11use crate::{item::CompletionKind, CompletionConfig, CompletionItem}; 14use crate::{item::CompletionKind, CompletionConfig, CompletionItem};
12 15
13/// Creates analysis from a multi-file fixture, returns positions marked with <|>. 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
25/// Creates analysis from a multi-file fixture, returns positions marked with $0.
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);
16 let mut database = RootDatabase::default(); 28 let mut database = RootDatabase::default();
17 database.apply_change(change_fixture.change); 29 database.apply_change(change_fixture.change);
18 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker (<|>)"); 30 let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)");
19 let offset = match range_or_offset { 31 let offset = match range_or_offset {
20 RangeOrOffset::Range(_) => panic!(), 32 RangeOrOffset::Range(_) => panic!(),
21 RangeOrOffset::Offset(it) => it, 33 RangeOrOffset::Offset(it) => it,
@@ -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(