1 //! Completes keywords, except:
2 //! - `self`, `super` and `crate`, as these are considered part of path completions.
3 //! - `await`, as this is a postfix completion we handle this in the postfix completions.
8 context::{NameRefContext, PathKind},
9 CompletionContext, CompletionItem, CompletionItemKind, Completions,
12 pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
13 if matches!(ctx.nameref_ctx(), Some(NameRefContext { record_expr: Some(_), .. })) {
14 cov_mark::hit!(no_keyword_completion_in_record_lit);
17 if ctx.is_non_trivial_path() {
18 cov_mark::hit!(no_keyword_completion_in_non_trivial_path);
21 if ctx.pattern_ctx.is_some() {
25 let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);
27 let expects_assoc_item = ctx.expects_assoc_item();
28 let has_block_expr_parent = ctx.has_block_expr_parent();
29 let expects_item = ctx.expects_item();
31 if let Some(PathKind::Vis { .. }) = ctx.path_kind() {
34 if ctx.has_unfinished_impl_or_trait_prev_sibling() {
35 add_keyword("where", "where");
36 if ctx.has_impl_prev_sibling() {
37 add_keyword("for", "for");
41 if ctx.previous_token_is(T![unsafe]) {
42 if expects_item || expects_assoc_item || has_block_expr_parent {
43 add_keyword("fn", "fn $1($2) {\n $0\n}")
46 if expects_item || has_block_expr_parent {
47 add_keyword("trait", "trait $1 {\n $0\n}");
48 add_keyword("impl", "impl $1 {\n $0\n}");
54 if ctx.qualifier_ctx.vis_node.is_none()
55 && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field())
57 add_keyword("pub(crate)", "pub(crate)");
58 add_keyword("pub(super)", "pub(super)");
59 add_keyword("pub", "pub");
62 if expects_item || expects_assoc_item || has_block_expr_parent {
63 add_keyword("unsafe", "unsafe");
64 add_keyword("fn", "fn $1($2) {\n $0\n}");
65 add_keyword("const", "const $0");
66 add_keyword("type", "type $0");
69 if expects_item || has_block_expr_parent {
70 if ctx.qualifier_ctx.vis_node.is_none() {
71 add_keyword("impl", "impl $1 {\n $0\n}");
72 add_keyword("extern", "extern $0");
74 add_keyword("use", "use $0");
75 add_keyword("trait", "trait $1 {\n $0\n}");
76 add_keyword("static", "static $0");
77 add_keyword("mod", "mod $0");
80 if expects_item || has_block_expr_parent {
81 add_keyword("enum", "enum $1 {\n $0\n}");
82 add_keyword("struct", "struct $0");
83 add_keyword("union", "union $1 {\n $0\n}");
87 pub(super) fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
88 let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
90 match ctx.config.snippet_cap {
92 if snippet.ends_with('}') && ctx.incomplete_let {
93 // complete block expression snippets with a trailing semicolon, if inside an incomplete let
94 cov_mark::hit!(let_semi);
95 item.insert_snippet(cap, format!("{};", snippet));
97 item.insert_snippet(cap, snippet);
101 item.insert_text(if snippet.contains('$') { kw } else { snippet });
109 use expect_test::{expect, Expect};
111 use crate::tests::{check_edit, completion_list};
113 fn check(ra_fixture: &str, expect: Expect) {
114 let actual = completion_list(ra_fixture);
115 expect.assert_eq(&actual)
119 fn test_else_edit_after_if() {
122 r#"fn quux() { if true { () } $0 }"#,
123 r#"fn quux() { if true { () } else {
130 fn test_keywords_after_unsafe_in_block_expr() {
132 r"fn my_fn() { unsafe $0 }",
144 fn test_completion_await_impls_future() {
151 fn foo(a: A) { a.$0 }
155 sn box Box::new(expr)
156 sn call function(expr)
161 sn match match expr {}
178 sn box Box::new(expr)
179 sn call function(expr)
184 sn match match expr {}
193 cov_mark::check!(let_semi);
197 fn main() { let x = $0 }
200 fn main() { let x = match $1 {