diff options
-rw-r--r-- | crates/completion/src/completions/keyword.rs | 58 | ||||
-rw-r--r-- | crates/completion/src/context.rs | 18 |
2 files changed, 69 insertions, 7 deletions
diff --git a/crates/completion/src/completions/keyword.rs b/crates/completion/src/completions/keyword.rs index effc3e4bf..c1af348dc 100644 --- a/crates/completion/src/completions/keyword.rs +++ b/crates/completion/src/completions/keyword.rs | |||
@@ -161,7 +161,17 @@ fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet | |||
161 | let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) | 161 | let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) |
162 | .kind(CompletionItemKind::Keyword); | 162 | .kind(CompletionItemKind::Keyword); |
163 | let builder = match ctx.config.snippet_cap { | 163 | let builder = match ctx.config.snippet_cap { |
164 | Some(cap) => builder.insert_snippet(cap, snippet), | 164 | Some(cap) => { |
165 | let tmp; | ||
166 | let snippet = if snippet.ends_with('}') && ctx.incomplete_let { | ||
167 | mark::hit!(let_semi); | ||
168 | tmp = format!("{};", snippet); | ||
169 | &tmp | ||
170 | } else { | ||
171 | snippet | ||
172 | }; | ||
173 | builder.insert_snippet(cap, snippet) | ||
174 | } | ||
165 | None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }), | 175 | None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }), |
166 | }; | 176 | }; |
167 | acc.add(builder.build()); | 177 | acc.add(builder.build()); |
@@ -601,4 +611,50 @@ fn foo() { | |||
601 | "#]], | 611 | "#]], |
602 | ); | 612 | ); |
603 | } | 613 | } |
614 | |||
615 | #[test] | ||
616 | fn let_semi() { | ||
617 | mark::check!(let_semi); | ||
618 | check_edit( | ||
619 | "match", | ||
620 | r#" | ||
621 | fn main() { let x = $0 } | ||
622 | "#, | ||
623 | r#" | ||
624 | fn main() { let x = match $0 {}; } | ||
625 | "#, | ||
626 | ); | ||
627 | |||
628 | check_edit( | ||
629 | "if", | ||
630 | r#" | ||
631 | fn main() { | ||
632 | let x = $0 | ||
633 | let y = 92; | ||
634 | } | ||
635 | "#, | ||
636 | r#" | ||
637 | fn main() { | ||
638 | let x = if $0 {}; | ||
639 | let y = 92; | ||
640 | } | ||
641 | "#, | ||
642 | ); | ||
643 | |||
644 | check_edit( | ||
645 | "loop", | ||
646 | r#" | ||
647 | fn main() { | ||
648 | let x = $0 | ||
649 | bar(); | ||
650 | } | ||
651 | "#, | ||
652 | r#" | ||
653 | fn main() { | ||
654 | let x = loop {$0}; | ||
655 | bar(); | ||
656 | } | ||
657 | "#, | ||
658 | ); | ||
659 | } | ||
604 | } | 660 | } |
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs index ebf28e887..d809460e2 100644 --- a/crates/completion/src/context.rs +++ b/crates/completion/src/context.rs | |||
@@ -92,6 +92,7 @@ pub(crate) struct CompletionContext<'a> { | |||
92 | pub(super) has_item_list_or_source_file_parent: bool, | 92 | pub(super) has_item_list_or_source_file_parent: bool, |
93 | pub(super) for_is_prev2: bool, | 93 | pub(super) for_is_prev2: bool, |
94 | pub(super) fn_is_prev: bool, | 94 | pub(super) fn_is_prev: bool, |
95 | pub(super) incomplete_let: bool, | ||
95 | pub(super) locals: Vec<(String, Local)>, | 96 | pub(super) locals: Vec<(String, Local)>, |
96 | } | 97 | } |
97 | 98 | ||
@@ -132,9 +133,9 @@ impl<'a> CompletionContext<'a> { | |||
132 | scope, | 133 | scope, |
133 | db, | 134 | db, |
134 | config, | 135 | config, |
136 | position, | ||
135 | original_token, | 137 | original_token, |
136 | token, | 138 | token, |
137 | position, | ||
138 | krate, | 139 | krate, |
139 | expected_type: None, | 140 | expected_type: None, |
140 | name_ref_syntax: None, | 141 | name_ref_syntax: None, |
@@ -155,30 +156,31 @@ impl<'a> CompletionContext<'a> { | |||
155 | is_expr: false, | 156 | is_expr: false, |
156 | is_new_item: false, | 157 | is_new_item: false, |
157 | dot_receiver: None, | 158 | dot_receiver: None, |
159 | dot_receiver_is_ambiguous_float_literal: false, | ||
158 | is_call: false, | 160 | is_call: false, |
159 | is_pattern_call: false, | 161 | is_pattern_call: false, |
160 | is_macro_call: false, | 162 | is_macro_call: false, |
161 | is_path_type: false, | 163 | is_path_type: false, |
162 | has_type_args: false, | 164 | has_type_args: false, |
163 | dot_receiver_is_ambiguous_float_literal: false, | ||
164 | attribute_under_caret: None, | 165 | attribute_under_caret: None, |
165 | mod_declaration_under_caret: None, | 166 | mod_declaration_under_caret: None, |
166 | unsafe_is_prev: false, | 167 | unsafe_is_prev: false, |
167 | in_loop_body: false, | 168 | if_is_prev: false, |
168 | ref_pat_parent: false, | ||
169 | bind_pat_parent: false, | ||
170 | block_expr_parent: false, | 169 | block_expr_parent: false, |
170 | bind_pat_parent: false, | ||
171 | ref_pat_parent: false, | ||
172 | in_loop_body: false, | ||
171 | has_trait_parent: false, | 173 | has_trait_parent: false, |
172 | has_impl_parent: false, | 174 | has_impl_parent: false, |
173 | inside_impl_trait_block: false, | 175 | inside_impl_trait_block: false, |
174 | has_field_list_parent: false, | 176 | has_field_list_parent: false, |
175 | trait_as_prev_sibling: false, | 177 | trait_as_prev_sibling: false, |
176 | impl_as_prev_sibling: false, | 178 | impl_as_prev_sibling: false, |
177 | if_is_prev: false, | ||
178 | is_match_arm: false, | 179 | is_match_arm: false, |
179 | has_item_list_or_source_file_parent: false, | 180 | has_item_list_or_source_file_parent: false, |
180 | for_is_prev2: false, | 181 | for_is_prev2: false, |
181 | fn_is_prev: false, | 182 | fn_is_prev: false, |
183 | incomplete_let: false, | ||
182 | locals, | 184 | locals, |
183 | }; | 185 | }; |
184 | 186 | ||
@@ -270,6 +272,10 @@ impl<'a> CompletionContext<'a> { | |||
270 | .filter(|module| module.item_list().is_none()); | 272 | .filter(|module| module.item_list().is_none()); |
271 | self.for_is_prev2 = for_is_prev2(syntax_element.clone()); | 273 | self.for_is_prev2 = for_is_prev2(syntax_element.clone()); |
272 | self.fn_is_prev = fn_is_prev(syntax_element.clone()); | 274 | self.fn_is_prev = fn_is_prev(syntax_element.clone()); |
275 | self.incomplete_let = | ||
276 | syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { | ||
277 | it.syntax().text_range().end() == syntax_element.text_range().end() | ||
278 | }); | ||
273 | } | 279 | } |
274 | 280 | ||
275 | fn fill( | 281 | fn fill( |