aboutsummaryrefslogtreecommitdiff
path: root/crates/completion
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2021-01-15 12:49:59 +0000
committerAleksey Kladov <[email protected]>2021-01-15 12:49:59 +0000
commitf2ba2048d1afb816623d037f265f4445a2f44b54 (patch)
treee5b5f19b0207028a0ac99d7b211d843cba6f9b8c /crates/completion
parent41ea2602017027e22f5a68df3d6ad98e2ae880f8 (diff)
Insert `;` when completing keywords in let
Diffstat (limited to 'crates/completion')
-rw-r--r--crates/completion/src/completions/keyword.rs58
-rw-r--r--crates/completion/src/context.rs18
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#"
621fn main() { let x = $0 }
622"#,
623 r#"
624fn main() { let x = match $0 {}; }
625"#,
626 );
627
628 check_edit(
629 "if",
630 r#"
631fn main() {
632 let x = $0
633 let y = 92;
634}
635"#,
636 r#"
637fn main() {
638 let x = if $0 {};
639 let y = 92;
640}
641"#,
642 );
643
644 check_edit(
645 "loop",
646 r#"
647fn main() {
648 let x = $0
649 bar();
650}
651"#,
652 r#"
653fn 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(