|
2 | 2 | //! - `self`, `super` and `crate`, as these are considered part of path completions.
|
3 | 3 | //! - `await`, as this is a postfix completion we handle this in the postfix completions.
|
4 | 4 |
|
5 |
| -use syntax::T; |
| 5 | +use syntax::ast::Item; |
6 | 6 |
|
7 |
| -use crate::{ |
8 |
| - context::{NameRefContext, PathKind}, |
9 |
| - CompletionContext, CompletionItem, CompletionItemKind, Completions, |
10 |
| -}; |
| 7 | +use crate::{context::NameRefContext, CompletionContext, Completions}; |
11 | 8 |
|
12 | 9 | 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); |
15 |
| - return; |
16 |
| - } |
17 |
| - if ctx.is_non_trivial_path() { |
18 |
| - cov_mark::hit!(no_keyword_completion_in_non_trivial_path); |
19 |
| - return; |
20 |
| - } |
21 |
| - if ctx.pattern_ctx.is_some() { |
22 |
| - return; |
23 |
| - } |
24 |
| - |
25 |
| - let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet); |
26 |
| - |
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(); |
30 |
| - |
31 |
| - if let Some(PathKind::Vis { .. }) = ctx.path_kind() { |
32 |
| - return; |
33 |
| - } |
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"); |
38 |
| - } |
39 |
| - return; |
40 |
| - } |
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}") |
| 10 | + let item = match ctx.nameref_ctx() { |
| 11 | + Some(NameRefContext { keyword: Some(item), record_expr: None, .. }) |
| 12 | + if !ctx.is_non_trivial_path() => |
| 13 | + { |
| 14 | + item |
44 | 15 | }
|
| 16 | + _ => return, |
| 17 | + }; |
45 | 18 |
|
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}"); |
49 |
| - } |
50 |
| - |
51 |
| - return; |
52 |
| - } |
53 |
| - |
54 |
| - if ctx.qualifier_ctx.vis_node.is_none() |
55 |
| - && (expects_item || ctx.expects_non_trait_assoc_item() || ctx.expect_field()) |
56 |
| - { |
57 |
| - add_keyword("pub(crate)", "pub(crate)"); |
58 |
| - add_keyword("pub(super)", "pub(super)"); |
59 |
| - add_keyword("pub", "pub"); |
60 |
| - } |
61 |
| - |
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"); |
67 |
| - } |
68 |
| - |
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"); |
73 |
| - } |
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"); |
78 |
| - } |
79 |
| - |
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}"); |
84 |
| - } |
85 |
| -} |
86 |
| - |
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); |
| 19 | + let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet); |
89 | 20 |
|
90 |
| - match ctx.config.snippet_cap { |
91 |
| - Some(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)); |
96 |
| - } else { |
97 |
| - item.insert_snippet(cap, snippet); |
| 21 | + match item { |
| 22 | + Item::Impl(it) => { |
| 23 | + if it.for_token().is_none() && it.trait_().is_none() && it.self_ty().is_some() { |
| 24 | + add_keyword("for", "for"); |
98 | 25 | }
|
| 26 | + add_keyword("where", "where"); |
99 | 27 | }
|
100 |
| - None => { |
101 |
| - item.insert_text(if snippet.contains('$') { kw } else { snippet }); |
| 28 | + Item::Enum(_) |
| 29 | + | Item::Fn(_) |
| 30 | + | Item::Struct(_) |
| 31 | + | Item::Trait(_) |
| 32 | + | Item::TypeAlias(_) |
| 33 | + | Item::Union(_) => { |
| 34 | + add_keyword("where", "where"); |
102 | 35 | }
|
103 |
| - }; |
104 |
| - item.add_to(acc); |
| 36 | + _ => (), |
| 37 | + } |
105 | 38 | }
|
106 | 39 |
|
107 | 40 | #[cfg(test)]
|
|
0 commit comments