diff options
Diffstat (limited to 'crates/completion/src')
-rw-r--r-- | crates/completion/src/completions/attribute.rs | 2 | ||||
-rw-r--r-- | crates/completion/src/completions/postfix.rs | 2 | ||||
-rw-r--r-- | crates/completion/src/completions/postfix/format_like.rs | 13 | ||||
-rw-r--r-- | crates/completion/src/completions/record.rs | 68 | ||||
-rw-r--r-- | crates/completion/src/completions/unqualified_path.rs | 15 | ||||
-rw-r--r-- | crates/completion/src/lib.rs | 2 |
6 files changed, 90 insertions, 12 deletions
diff --git a/crates/completion/src/completions/attribute.rs b/crates/completion/src/completions/attribute.rs index 19ce2482f..8695eed39 100644 --- a/crates/completion/src/completions/attribute.rs +++ b/crates/completion/src/completions/attribute.rs | |||
@@ -234,7 +234,7 @@ fn parse_comma_sep_input(derive_input: ast::TokenTree) -> Result<FxHashSet<Strin | |||
234 | current_derive = String::new(); | 234 | current_derive = String::new(); |
235 | } | 235 | } |
236 | } else { | 236 | } else { |
237 | current_derive.push_str(token.to_string().trim()); | 237 | current_derive.push_str(token.text().trim()); |
238 | } | 238 | } |
239 | } | 239 | } |
240 | 240 | ||
diff --git a/crates/completion/src/completions/postfix.rs b/crates/completion/src/completions/postfix.rs index d6db82a93..3883d6d21 100644 --- a/crates/completion/src/completions/postfix.rs +++ b/crates/completion/src/completions/postfix.rs | |||
@@ -502,7 +502,7 @@ fn main() { | |||
502 | #[test] | 502 | #[test] |
503 | fn postfix_completion_for_format_like_strings() { | 503 | fn postfix_completion_for_format_like_strings() { |
504 | check_edit( | 504 | check_edit( |
505 | "fmt", | 505 | "format", |
506 | r#"fn main() { "{some_var:?}".<|> }"#, | 506 | r#"fn main() { "{some_var:?}".<|> }"#, |
507 | r#"fn main() { format!("{:?}", some_var) }"#, | 507 | r#"fn main() { format!("{:?}", some_var) }"#, |
508 | ); | 508 | ); |
diff --git a/crates/completion/src/completions/postfix/format_like.rs b/crates/completion/src/completions/postfix/format_like.rs index 88ba86acb..def4b13fb 100644 --- a/crates/completion/src/completions/postfix/format_like.rs +++ b/crates/completion/src/completions/postfix/format_like.rs | |||
@@ -22,7 +22,7 @@ use syntax::ast::{self, AstToken}; | |||
22 | 22 | ||
23 | /// Mapping ("postfix completion item" => "macro to use") | 23 | /// Mapping ("postfix completion item" => "macro to use") |
24 | static KINDS: &[(&str, &str)] = &[ | 24 | static KINDS: &[(&str, &str)] = &[ |
25 | ("fmt", "format!"), | 25 | ("format", "format!"), |
26 | ("panic", "panic!"), | 26 | ("panic", "panic!"), |
27 | ("println", "println!"), | 27 | ("println", "println!"), |
28 | ("eprintln", "eprintln!"), | 28 | ("eprintln", "eprintln!"), |
@@ -108,7 +108,8 @@ impl FormatStrParser { | |||
108 | // "{MyStruct { val_a: 0, val_b: 1 }}". | 108 | // "{MyStruct { val_a: 0, val_b: 1 }}". |
109 | let mut inexpr_open_count = 0; | 109 | let mut inexpr_open_count = 0; |
110 | 110 | ||
111 | for chr in self.input.chars() { | 111 | let mut chars = self.input.chars().peekable(); |
112 | while let Some(chr) = chars.next() { | ||
112 | match (self.state, chr) { | 113 | match (self.state, chr) { |
113 | (State::NotExpr, '{') => { | 114 | (State::NotExpr, '{') => { |
114 | self.output.push(chr); | 115 | self.output.push(chr); |
@@ -157,6 +158,11 @@ impl FormatStrParser { | |||
157 | inexpr_open_count -= 1; | 158 | inexpr_open_count -= 1; |
158 | } | 159 | } |
159 | } | 160 | } |
161 | (State::Expr, ':') if chars.peek().copied() == Some(':') => { | ||
162 | // path seperator | ||
163 | current_expr.push_str("::"); | ||
164 | chars.next(); | ||
165 | } | ||
160 | (State::Expr, ':') => { | 166 | (State::Expr, ':') => { |
161 | if inexpr_open_count == 0 { | 167 | if inexpr_open_count == 0 { |
162 | // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}" | 168 | // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}" |
@@ -249,6 +255,9 @@ mod tests { | |||
249 | expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]], | 255 | expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]], |
250 | ), | 256 | ), |
251 | ("{ 2 + 2 }", expect![["{}; 2 + 2"]]), | 257 | ("{ 2 + 2 }", expect![["{}; 2 + 2"]]), |
258 | ("{strsim::jaro_winkle(a)}", expect![["{}; strsim::jaro_winkle(a)"]]), | ||
259 | ("{foo::bar::baz()}", expect![["{}; foo::bar::baz()"]]), | ||
260 | ("{foo::bar():?}", expect![["{:?}; foo::bar()"]]), | ||
252 | ]; | 261 | ]; |
253 | 262 | ||
254 | for (input, output) in test_vector { | 263 | for (input, output) in test_vector { |
diff --git a/crates/completion/src/completions/record.rs b/crates/completion/src/completions/record.rs index 91bf4a8ad..e58b9a274 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#" |
@@ -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#" | ||
128 | struct S { foo: u32, bar: usize } | ||
129 | |||
130 | impl core::default::Default for S { | ||
131 | fn default() -> Self { | ||
132 | S { | ||
133 | foo: 0, | ||
134 | bar: 0, | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | fn process(f: S) { | ||
140 | let other = S { | ||
141 | foo: 5, | ||
142 | .<|> | ||
143 | }; | ||
144 | } | ||
145 | "#, | ||
146 | r#" | ||
147 | struct S { foo: u32, bar: usize } | ||
148 | |||
149 | impl core::default::Default for S { | ||
150 | fn default() -> Self { | ||
151 | S { | ||
152 | foo: 0, | ||
153 | bar: 0, | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | fn 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#" |
107 | struct S { foo: u32, bar: usize } | 171 | struct S { foo: u32, bar: usize } |
diff --git a/crates/completion/src/completions/unqualified_path.rs b/crates/completion/src/completions/unqualified_path.rs index d09849752..81a6d00e2 100644 --- a/crates/completion/src/completions/unqualified_path.rs +++ b/crates/completion/src/completions/unqualified_path.rs | |||
@@ -101,8 +101,9 @@ fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext, ty: &T | |||
101 | // | 101 | // |
102 | // .Fuzzy search details | 102 | // .Fuzzy search details |
103 | // | 103 | // |
104 | // To avoid an excessive amount of the results returned, completion input is checked for inclusion in the identifiers only | 104 | // To avoid an excessive amount of the results returned, completion input is checked for inclusion in the names only |
105 | // (i.e. in `HashMap` in the `std::collections::HashMap` path), also not in the module indentifiers. | 105 | // (i.e. in `HashMap` in the `std::collections::HashMap` path). |
106 | // For the same reasons, avoids searching for any imports for inputs with their length less that 2 symbols. | ||
106 | // | 107 | // |
107 | // .Merge Behavior | 108 | // .Merge Behavior |
108 | // | 109 | // |
@@ -126,15 +127,20 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
126 | let _p = profile::span("fuzzy_completion"); | 127 | let _p = profile::span("fuzzy_completion"); |
127 | let potential_import_name = ctx.token.to_string(); | 128 | let potential_import_name = ctx.token.to_string(); |
128 | 129 | ||
130 | if potential_import_name.len() < 2 { | ||
131 | return None; | ||
132 | } | ||
133 | |||
129 | let current_module = ctx.scope.module()?; | 134 | let current_module = ctx.scope.module()?; |
130 | let anchor = ctx.name_ref_syntax.as_ref()?; | 135 | let anchor = ctx.name_ref_syntax.as_ref()?; |
131 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; | 136 | let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; |
132 | 137 | ||
138 | let user_input_lowercased = potential_import_name.to_lowercase(); | ||
133 | let mut all_mod_paths = imports_locator::find_similar_imports( | 139 | let mut all_mod_paths = imports_locator::find_similar_imports( |
134 | &ctx.sema, | 140 | &ctx.sema, |
135 | ctx.krate?, | 141 | ctx.krate?, |
136 | Some(100), | 142 | Some(40), |
137 | &potential_import_name, | 143 | potential_import_name, |
138 | true, | 144 | true, |
139 | ) | 145 | ) |
140 | .filter_map(|import_candidate| { | 146 | .filter_map(|import_candidate| { |
@@ -150,7 +156,6 @@ fn fuzzy_completion(acc: &mut Completions, ctx: &CompletionContext) -> Option<() | |||
150 | .filter(|(mod_path, _)| mod_path.len() > 1) | 156 | .filter(|(mod_path, _)| mod_path.len() > 1) |
151 | .collect::<Vec<_>>(); | 157 | .collect::<Vec<_>>(); |
152 | 158 | ||
153 | let user_input_lowercased = potential_import_name.to_lowercase(); | ||
154 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { | 159 | all_mod_paths.sort_by_cached_key(|(mod_path, _)| { |
155 | compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased) | 160 | compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased) |
156 | }); | 161 | }); |
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs index 8e27bb153..c57d05bbe 100644 --- a/crates/completion/src/lib.rs +++ b/crates/completion/src/lib.rs | |||
@@ -137,7 +137,7 @@ pub fn resolve_completion_edits( | |||
137 | config: &CompletionConfig, | 137 | config: &CompletionConfig, |
138 | position: FilePosition, | 138 | position: FilePosition, |
139 | full_import_path: &str, | 139 | full_import_path: &str, |
140 | imported_name: &str, | 140 | imported_name: String, |
141 | ) -> Option<Vec<TextEdit>> { | 141 | ) -> Option<Vec<TextEdit>> { |
142 | let ctx = CompletionContext::new(db, position, config)?; | 142 | let ctx = CompletionContext::new(db, position, config)?; |
143 | let anchor = ctx.name_ref_syntax.as_ref()?; | 143 | let anchor = ctx.name_ref_syntax.as_ref()?; |