aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Rakhmanov <[email protected]>2020-06-13 09:43:39 +0100
committerMikhail Rakhmanov <[email protected]>2020-06-13 09:43:39 +0100
commit912f38200fb6c8c6cea750a84c04de810992dec7 (patch)
tree7786c87c7fbfeaaffa075bb269de63ffdf712e5d
parent16bbf4ab7f132e6e5e5318dccdef9a5d71afdd7f (diff)
Add keywords completions on source file position
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs115
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs8
-rw-r--r--crates/ra_ide/src/completion/patterns.rs22
3 files changed, 124 insertions, 21 deletions
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs
index 025097e49..d016f0c7c 100644
--- a/crates/ra_ide/src/completion/complete_keyword.rs
+++ b/crates/ra_ide/src/completion/complete_keyword.rs
@@ -66,48 +66,83 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
66 return; 66 return;
67 } 67 }
68 if ctx.unsafe_is_prev { 68 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 );
70 add_keyword( 76 add_keyword(
71 ctx, 77 ctx,
72 acc, 78 acc,
73 "trait", 79 "trait",
74 "trait $0 {}", 80 "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,
76 ); 83 );
77 add_keyword( 84 add_keyword(
78 ctx, 85 ctx,
79 acc, 86 acc,
80 "impl", 87 "impl",
81 "impl $0 {}", 88 "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,
83 ); 91 );
84 return; 92 return;
85 } 93 }
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 );
87 add_keyword( 101 add_keyword(
88 ctx, 102 ctx,
89 acc, 103 acc,
90 "use", 104 "use",
91 "use ", 105 "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,
93 ); 108 );
94 add_keyword( 109 add_keyword(
95 ctx, 110 ctx,
96 acc, 111 acc,
97 "impl", 112 "impl",
98 "impl $0 {}", 113 "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,
100 ); 116 );
101 add_keyword( 117 add_keyword(
102 ctx, 118 ctx,
103 acc, 119 acc,
104 "trait", 120 "trait",
105 "trait $0 {}", 121 "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,
107 ); 145 );
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);
111 add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm); 146 add_keyword(ctx, acc, "match", "match $0 {}", ctx.block_expr_parent || ctx.is_match_arm);
112 add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm); 147 add_keyword(ctx, acc, "loop", "loop {$0}", ctx.block_expr_parent || ctx.is_match_arm);
113 add_keyword(ctx, acc, "while", "while $0 {}", ctx.block_expr_parent); 148 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
127 acc, 162 acc,
128 "mod", 163 "mod",
129 "mod $0 {}", 164 "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,
131 ); 167 );
132 add_keyword(ctx, acc, "mut", "mut ", ctx.bind_pat_parent || ctx.ref_pat_parent); 168 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); 169 add_keyword(
134 add_keyword(ctx, acc, "type", "type ", ctx.is_new_item || ctx.block_expr_parent); 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 );
135 add_keyword( 183 add_keyword(
136 ctx, 184 ctx,
137 acc, 185 acc,
138 "static", 186 "static",
139 "static ", 187 "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,
141 ); 190 );
142 add_keyword( 191 add_keyword(
143 ctx, 192 ctx,
144 acc, 193 acc,
145 "extern", 194 "extern",
146 "extern ", 195 "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,
148 ); 198 );
149 add_keyword( 199 add_keyword(
150 ctx, 200 ctx,
151 acc, 201 acc,
152 "unsafe", 202 "unsafe",
153 "unsafe ", 203 "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,
155 ); 205 );
156 add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt); 206 add_keyword(ctx, acc, "continue", "continue;", ctx.in_loop_body && ctx.can_be_stmt);
157 add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt); 207 add_keyword(ctx, acc, "break", "break;", ctx.in_loop_body && ctx.can_be_stmt);
158 add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt); 208 add_keyword(ctx, acc, "continue", "continue", ctx.in_loop_body && !ctx.can_be_stmt);
159 add_keyword(ctx, acc, "break", "break", ctx.in_loop_body && !ctx.can_be_stmt); 209 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 );
161 217
162 if !ctx.is_trivial_path { 218 if !ctx.is_trivial_path {
163 return; 219 return;
@@ -227,6 +283,31 @@ mod tests {
227 } 283 }
228 284
229 #[test] 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
310 #[test]
230 fn test_keywords_in_function() { 311 fn test_keywords_in_function() {
231 assert_debug_snapshot!( 312 assert_debug_snapshot!(
232 get_keyword_completions(r"fn quux() { <|> }"), 313 get_keyword_completions(r"fn quux() { <|> }"),
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs
index 2f96861ca..9f4c582d0 100644
--- a/crates/ra_ide/src/completion/completion_context.rs
+++ b/crates/ra_ide/src/completion/completion_context.rs
@@ -13,8 +13,8 @@ use ra_text_edit::Indel;
13 13
14use super::patterns::{ 14use super::patterns::{
15 has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, 15 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, 16 has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
17 is_match_arm, unsafe_is_prev, 17 has_trait_parent, if_is_prev, is_in_loop_body, is_match_arm, unsafe_is_prev,
18}; 18};
19use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; 19use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition};
20use test_utils::mark; 20use test_utils::mark;
@@ -76,6 +76,7 @@ pub(crate) struct CompletionContext<'a> {
76 pub(super) trait_as_prev_sibling: bool, 76 pub(super) trait_as_prev_sibling: bool,
77 pub(super) impl_as_prev_sibling: bool, 77 pub(super) impl_as_prev_sibling: bool,
78 pub(super) is_match_arm: bool, 78 pub(super) is_match_arm: bool,
79 pub(super) has_item_list_or_source_file_parent: bool,
79} 80}
80 81
81impl<'a> CompletionContext<'a> { 82impl<'a> CompletionContext<'a> {
@@ -145,6 +146,7 @@ impl<'a> CompletionContext<'a> {
145 impl_as_prev_sibling: false, 146 impl_as_prev_sibling: false,
146 if_is_prev: false, 147 if_is_prev: false,
147 is_match_arm: false, 148 is_match_arm: false,
149 has_item_list_or_source_file_parent: false,
148 }; 150 };
149 151
150 let mut original_file = original_file.syntax().clone(); 152 let mut original_file = original_file.syntax().clone();
@@ -229,6 +231,8 @@ impl<'a> CompletionContext<'a> {
229 self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone()); 231 self.impl_as_prev_sibling = has_impl_as_prev_sibling(syntax_element.clone());
230 self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone()); 232 self.trait_as_prev_sibling = has_trait_as_prev_sibling(syntax_element.clone());
231 self.is_match_arm = is_match_arm(syntax_element.clone()); 233 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());
232 } 236 }
233 237
234 fn fill( 238 fn fill(
diff --git a/crates/ra_ide/src/completion/patterns.rs b/crates/ra_ide/src/completion/patterns.rs
index 464032cb4..fdcd3faa5 100644
--- a/crates/ra_ide/src/completion/patterns.rs
+++ b/crates/ra_ide/src/completion/patterns.rs
@@ -38,6 +38,14 @@ pub(crate) fn has_ref_parent(element: SyntaxElement) -> bool {
38 .is_some() 38 .is_some()
39} 39}
40 40
41pub(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
41pub(crate) fn is_match_arm(element: SyntaxElement) -> bool { 49pub(crate) fn is_match_arm(element: SyntaxElement) -> bool {
42 not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some() 50 not_same_range_ancestor(element.clone()).filter(|it| it.kind() == MATCH_ARM).is_some()
43 && previous_sibling_or_ancestor_sibling(element) 51 && previous_sibling_or_ancestor_sibling(element)
@@ -139,8 +147,8 @@ fn previous_sibling_or_ancestor_sibling(element: SyntaxElement) -> Option<Syntax
139mod tests { 147mod tests {
140 use super::{ 148 use super::{
141 has_bind_pat_parent, has_block_expr_parent, has_impl_as_prev_sibling, has_impl_parent, 149 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, 150 has_item_list_or_source_file_parent, has_ref_parent, has_trait_as_prev_sibling,
143 unsafe_is_prev, 151 has_trait_parent, if_is_prev, is_match_arm, unsafe_is_prev,
144 }; 152 };
145 use crate::completion::test_utils::check_pattern_is_applicable; 153 use crate::completion::test_utils::check_pattern_is_applicable;
146 154
@@ -203,4 +211,14 @@ mod tests {
203 fn test_is_match_arm() { 211 fn test_is_match_arm() {
204 check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm); 212 check_pattern_is_applicable(r"fn my_fn() { match () { () => m<|> } }", is_match_arm);
205 } 213 }
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 }
206} 224}