From f2ba2048d1afb816623d037f265f4445a2f44b54 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Jan 2021 15:49:59 +0300 Subject: Insert `;` when completing keywords in let --- crates/completion/src/completions/keyword.rs | 58 +++++++++++++++++++++++++++- crates/completion/src/context.rs | 18 ++++++--- 2 files changed, 69 insertions(+), 7 deletions(-) (limited to 'crates') 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 let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) .kind(CompletionItemKind::Keyword); let builder = match ctx.config.snippet_cap { - Some(cap) => builder.insert_snippet(cap, snippet), + Some(cap) => { + let tmp; + let snippet = if snippet.ends_with('}') && ctx.incomplete_let { + mark::hit!(let_semi); + tmp = format!("{};", snippet); + &tmp + } else { + snippet + }; + builder.insert_snippet(cap, snippet) + } None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }), }; acc.add(builder.build()); @@ -601,4 +611,50 @@ fn foo() { "#]], ); } + + #[test] + fn let_semi() { + mark::check!(let_semi); + check_edit( + "match", + r#" +fn main() { let x = $0 } +"#, + r#" +fn main() { let x = match $0 {}; } +"#, + ); + + check_edit( + "if", + r#" +fn main() { + let x = $0 + let y = 92; +} +"#, + r#" +fn main() { + let x = if $0 {}; + let y = 92; +} +"#, + ); + + check_edit( + "loop", + r#" +fn main() { + let x = $0 + bar(); +} +"#, + r#" +fn main() { + let x = loop {$0}; + bar(); +} +"#, + ); + } } 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> { pub(super) has_item_list_or_source_file_parent: bool, pub(super) for_is_prev2: bool, pub(super) fn_is_prev: bool, + pub(super) incomplete_let: bool, pub(super) locals: Vec<(String, Local)>, } @@ -132,9 +133,9 @@ impl<'a> CompletionContext<'a> { scope, db, config, + position, original_token, token, - position, krate, expected_type: None, name_ref_syntax: None, @@ -155,30 +156,31 @@ impl<'a> CompletionContext<'a> { is_expr: false, is_new_item: false, dot_receiver: None, + dot_receiver_is_ambiguous_float_literal: false, is_call: false, is_pattern_call: false, is_macro_call: false, is_path_type: false, has_type_args: false, - dot_receiver_is_ambiguous_float_literal: false, attribute_under_caret: None, mod_declaration_under_caret: None, unsafe_is_prev: false, - in_loop_body: false, - ref_pat_parent: false, - bind_pat_parent: false, + if_is_prev: false, block_expr_parent: false, + bind_pat_parent: false, + ref_pat_parent: false, + in_loop_body: false, has_trait_parent: false, has_impl_parent: false, inside_impl_trait_block: false, has_field_list_parent: false, trait_as_prev_sibling: false, impl_as_prev_sibling: false, - if_is_prev: false, is_match_arm: false, has_item_list_or_source_file_parent: false, for_is_prev2: false, fn_is_prev: false, + incomplete_let: false, locals, }; @@ -270,6 +272,10 @@ impl<'a> CompletionContext<'a> { .filter(|module| module.item_list().is_none()); self.for_is_prev2 = for_is_prev2(syntax_element.clone()); self.fn_is_prev = fn_is_prev(syntax_element.clone()); + self.incomplete_let = + syntax_element.ancestors().take(6).find_map(ast::LetStmt::cast).map_or(false, |it| { + it.syntax().text_range().end() == syntax_element.text_range().end() + }); } fn fill( -- cgit v1.2.3