aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/completions
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/completions')
-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
14 files changed, 426 insertions, 364 deletions
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#"