Skip to content

Commit 912f382

Browse files
committed
Add keywords completions on source file position
1 parent 16bbf4a commit 912f382

File tree

3 files changed

+124
-21
lines changed

3 files changed

+124
-21
lines changed

crates/ra_ide/src/completion/complete_keyword.rs

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,48 +66,83 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
6666
return;
6767
}
6868
if ctx.unsafe_is_prev {
69-
add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
69+
add_keyword(
70+
ctx,
71+
acc,
72+
"fn",
73+
"fn $0() {}",
74+
ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent,
75+
);
7076
add_keyword(
7177
ctx,
7278
acc,
7379
"trait",
7480
"trait $0 {}",
75-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
81+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
82+
|| ctx.block_expr_parent,
7683
);
7784
add_keyword(
7885
ctx,
7986
acc,
8087
"impl",
8188
"impl $0 {}",
82-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
89+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
90+
|| ctx.block_expr_parent,
8391
);
8492
return;
8593
}
86-
add_keyword(ctx, acc, "fn", "fn $0() {}", ctx.is_new_item || ctx.block_expr_parent);
94+
add_keyword(
95+
ctx,
96+
acc,
97+
"fn",
98+
"fn $0() {}",
99+
ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent,
100+
);
87101
add_keyword(
88102
ctx,
89103
acc,
90104
"use",
91105
"use ",
92-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
106+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
107+
|| ctx.block_expr_parent,
93108
);
94109
add_keyword(
95110
ctx,
96111
acc,
97112
"impl",
98113
"impl $0 {}",
99-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
114+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
115+
|| ctx.block_expr_parent,
100116
);
101117
add_keyword(
102118
ctx,
103119
acc,
104120
"trait",
105121
"trait $0 {}",
106-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
122+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
123+
|| ctx.block_expr_parent,
124+
);
125+
add_keyword(
126+
ctx,
127+
acc,
128+
"enum",
129+
"enum $0 {}",
130+
ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent,
131+
);
132+
add_keyword(
133+
ctx,
134+
acc,
135+
"struct",
136+
"struct $0 {}",
137+
ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent,
138+
);
139+
add_keyword(
140+
ctx,
141+
acc,
142+
"union",
143+
"union $0 {}",
144+
ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent,
107145
);
108-
add_keyword(ctx, acc, "enum", "enum $0 {}", ctx.is_new_item && !has_trait_or_impl_parent);
109-
add_keyword(ctx, acc, "struct", "struct $0 {}", ctx.is_new_item && !has_trait_or_impl_parent);
110-
add_keyword(ctx, acc, "union", "union $0 {}", ctx.is_new_item && !has_trait_or_impl_parent);
111146
add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm);
112147
add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm);
113148
add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent);
@@ -127,37 +162,58 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
127162
acc,
128163
"mod",
129164
"mod $0 {}",
130-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
165+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
166+
|| ctx.block_expr_parent,
131167
);
132168
add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent);
133-
add_keyword(ctx, acc, "const", "const ", ctx.is_new_item || ctx.block_expr_parent);
134-
add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent);
169+
add_keyword(
170+
ctx,
171+
acc,
172+
"const",
173+
"const ",
174+
ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent,
175+
);
176+
add_keyword(
177+
ctx,
178+
acc,
179+
"type",
180+
"type ",
181+
ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent,
182+
);
135183
add_keyword(
136184
ctx,
137185
acc,
138186
"static",
139187
"static ",
140-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
188+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
189+
|| ctx.block_expr_parent,
141190
);
142191
add_keyword(
143192
ctx,
144193
acc,
145194
"extern",
146195
"extern ",
147-
(ctx.is_new_item && !has_trait_or_impl_parent) || ctx.block_expr_parent,
196+
(ctx.has_item_list_or_source_file_parent && !has_trait_or_impl_parent)
197+
|| ctx.block_expr_parent,
148198
);
149199
add_keyword(
150200
ctx,
151201
acc,
152202
"unsafe",
153203
"unsafe ",
154-
ctx.is_new_item || ctx.block_expr_parent || ctx.is_match_arm,
204+
ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent || ctx.is_match_arm,
155205
);
156206
add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt);
157207
add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt);
158208
add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt);
159209
add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt);
160-
add_keyword(ctx, acc, "pub", "pub ", ctx.is_new_item && !ctx.has_trait_parent);
210+
add_keyword(
211+
ctx,
212+
acc,
213+
"pub",
214+
"pub ",
215+
ctx.has_item_list_or_source_file_parent && !ctx.has_trait_parent,
216+
);
161217

162218
if !ctx.is_trivial_path {
163219
return;
@@ -226,6 +282,31 @@ mod tests {
226282
);
227283
}
228284

285+
#[test]
286+
fn test_keywords_at_source_file_level() {
287+
assert_debug_snapshot!(
288+
get_keyword_completions(r"m<|>"),
289+
@r###"
290+
[
291+
"kw const",
292+
"kw enum",
293+
"kw extern",
294+
"kw fn",
295+
"kw impl",
296+
"kw mod",
297+
"kw pub",
298+
"kw static",
299+
"kw struct",
300+
"kw trait",
301+
"kw type",
302+
"kw union",
303+
"kw unsafe",
304+
"kw use",
305+
]
306+
"###
307+
);
308+
}
309+
229310
#[test]
230311
fn test_keywords_in_function() {
231312
assert_debug_snapshot!(

crates/ra_ide/src/completion/completion_context.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ use ra_text_edit::Indel;
1313

1414
use super::patterns::{
1515
has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent,
16-
has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, if_is_prev, is_in_loop_body,
17-
is_match_arm, unsafe_is_prev,
16+
has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
17+
has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev,
1818
};
1919
use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
2020
use test_utils::mark;
@@ -76,6 +76,7 @@ pub(crate) struct CompletionContext<'a> {
7676
pub(super) trait_as_prev_sibling: bool,
7777
pub(super) impl_as_prev_sibling: bool,
7878
pub(super) is_match_arm: bool,
79+
pub(super) has_item_list_or_source_file_parent: bool,
7980
}
8081

8182
impl<'a> CompletionContext<'a> {
@@ -145,6 +146,7 @@ impl<'a> CompletionContext<'a> {
145146
impl_as_prev_sibling: false,
146147
if_is_prev: false,
147148
is_match_arm: false,
149+
has_item_list_or_source_file_parent: false,
148150
};
149151

150152
let mut original_file = original_file.syntax().clone();
@@ -229,6 +231,8 @@ impl<'a> CompletionContext<'a> {
229231
self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
230232
self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
231233
self.is_match_arm = is_match_arm(syntax_element.clone());
234+
self.has_item_list_or_source_file_parent =
235+
has_item_list_or_source_file_parent(syntax_element.clone());
232236
}
233237

234238
fn fill(

crates/ra_ide/src/completion/patterns.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool {
3838
.is_some()
3939
}
4040

41+
pub(crate) fn has_item_list_or_source_file_parent(element: SyntaxElement) -> bool {
42+
let ancestor = not_same_range_ancestor(element);
43+
if !ancestor.is_some() {
44+
return true;
45+
}
46+
ancestor.filter(|it| it.kind() == SOURCE_FILE || it.kind() == ITEM_LIST).is_some()
47+
}
48+
4149
pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
4250
not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some()
4351
&& previous_sibling_or_ancestor_sibling(element)
@@ -139,8 +147,8 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax
139147
mod tests {
140148
use super::{
141149
has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent,
142-
has_ref_parent, has_trait_as_prev_sibling, has_trait_parent, if_is_prev, is_match_arm,
143-
unsafe_is_prev,
150+
has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
151+
has_trait_parent, if_is_prev, is_match_arm, unsafe_is_prev,
144152
};
145153
use crate::completion::test_utils::check_pattern_is_applicable;
146154

@@ -203,4 +211,14 @@ mod tests {
203211
fn test_is_match_arm() {
204212
check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm);
205213
}
214+
215+
#[test]
216+
fn test_has_source_file_parent() {
217+
check_pattern_is_applicable(r"i<|>", has_item_list_or_source_file_parent);
218+
}
219+
220+
#[test]
221+
fn test_has_item_list_parent() {
222+
check_pattern_is_applicable(r"impl { f<|> }", has_item_list_or_source_file_parent);
223+
}
206224
}

0 commit comments

Comments
 (0)