diff options
Diffstat (limited to 'crates/ra_analysis/src')
-rw-r--r-- | crates/ra_analysis/src/completion/complete_keyword.rs | 55 | ||||
-rw-r--r-- | crates/ra_analysis/src/completion/completion_context.rs | 32 |
2 files changed, 67 insertions, 20 deletions
diff --git a/crates/ra_analysis/src/completion/complete_keyword.rs b/crates/ra_analysis/src/completion/complete_keyword.rs index 2869e67e0..d70fdaada 100644 --- a/crates/ra_analysis/src/completion/complete_keyword.rs +++ b/crates/ra_analysis/src/completion/complete_keyword.rs | |||
@@ -32,8 +32,13 @@ pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte | |||
32 | acc.add(keyword("else if", "else if $0 {}")); | 32 | acc.add(keyword("else if", "else if $0 {}")); |
33 | } | 33 | } |
34 | if is_in_loop_body(ctx.leaf) { | 34 | if is_in_loop_body(ctx.leaf) { |
35 | acc.add(keyword("continue", "continue")); | 35 | if ctx.can_be_stmt { |
36 | acc.add(keyword("break", "break")); | 36 | acc.add(keyword("continue", "continue;")); |
37 | acc.add(keyword("break", "break;")); | ||
38 | } else { | ||
39 | acc.add(keyword("continue", "continue")); | ||
40 | acc.add(keyword("break", "break")); | ||
41 | } | ||
37 | } | 42 | } |
38 | acc.add_all(complete_return(fn_def, ctx.can_be_stmt)); | 43 | acc.add_all(complete_return(fn_def, ctx.can_be_stmt)); |
39 | } | 44 | } |
@@ -186,6 +191,24 @@ mod tests { | |||
186 | return "return $0;" | 191 | return "return $0;" |
187 | "#, | 192 | "#, |
188 | ); | 193 | ); |
194 | check_keyword_completion( | ||
195 | r" | ||
196 | fn quux() -> i32 { | ||
197 | if condition { | ||
198 | <|> | ||
199 | } | ||
200 | let x = 92; | ||
201 | x | ||
202 | } | ||
203 | ", | ||
204 | r#" | ||
205 | if "if $0 {}" | ||
206 | match "match $0 {}" | ||
207 | while "while $0 {}" | ||
208 | loop "loop {$0}" | ||
209 | return "return $0;" | ||
210 | "#, | ||
211 | ); | ||
189 | } | 212 | } |
190 | 213 | ||
191 | #[test] | 214 | #[test] |
@@ -201,8 +224,8 @@ mod tests { | |||
201 | match "match $0 {}" | 224 | match "match $0 {}" |
202 | while "while $0 {}" | 225 | while "while $0 {}" |
203 | loop "loop {$0}" | 226 | loop "loop {$0}" |
204 | continue "continue" | 227 | continue "continue;" |
205 | break "break" | 228 | break "break;" |
206 | return "return $0;" | 229 | return "return $0;" |
207 | "#, | 230 | "#, |
208 | ); | 231 | ); |
@@ -222,4 +245,28 @@ mod tests { | |||
222 | "#, | 245 | "#, |
223 | ); | 246 | ); |
224 | } | 247 | } |
248 | |||
249 | #[test] | ||
250 | fn no_semi_after_break_continue_in_expr() { | ||
251 | check_keyword_completion( | ||
252 | r" | ||
253 | fn f() { | ||
254 | loop { | ||
255 | match () { | ||
256 | () => br<|> | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | ", | ||
261 | r#" | ||
262 | if "if $0 {}" | ||
263 | match "match $0 {}" | ||
264 | while "while $0 {}" | ||
265 | loop "loop {$0}" | ||
266 | continue "continue" | ||
267 | break "break" | ||
268 | return "return" | ||
269 | "#, | ||
270 | ) | ||
271 | } | ||
225 | } | 272 | } |
diff --git a/crates/ra_analysis/src/completion/completion_context.rs b/crates/ra_analysis/src/completion/completion_context.rs index 4685c9328..4584f355d 100644 --- a/crates/ra_analysis/src/completion/completion_context.rs +++ b/crates/ra_analysis/src/completion/completion_context.rs | |||
@@ -148,24 +148,24 @@ impl<'a> CompletionContext<'a> { | |||
148 | if path.qualifier().is_none() { | 148 | if path.qualifier().is_none() { |
149 | self.is_trivial_path = true; | 149 | self.is_trivial_path = true; |
150 | 150 | ||
151 | self.can_be_stmt = match name_ref | 151 | // Find either enclosing expr statement (thing with `;`) or a |
152 | // block. If block, check that we are the last expr. | ||
153 | self.can_be_stmt = name_ref | ||
152 | .syntax() | 154 | .syntax() |
153 | .ancestors() | 155 | .ancestors() |
154 | .filter_map(ast::ExprStmt::cast) | 156 | .find_map(|node| { |
155 | .next() | 157 | if let Some(stmt) = ast::ExprStmt::cast(node) { |
156 | { | 158 | return Some(stmt.syntax().range() == name_ref.syntax().range()); |
157 | None => { | 159 | } |
158 | name_ref | 160 | if let Some(block) = ast::Block::cast(node) { |
159 | .syntax() | 161 | return Some( |
160 | .ancestors() | 162 | block.expr().map(|e| e.syntax().range()) |
161 | .filter_map(ast::Block::cast) | 163 | == Some(name_ref.syntax().range()), |
162 | .next() | 164 | ); |
163 | .and_then(|block| block.expr()) | 165 | } |
164 | .map(|e| e.syntax().range()) | 166 | None |
165 | == Some(name_ref.syntax().range()) | 167 | }) |
166 | } | 168 | .unwrap_or(false); |
167 | Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range(), | ||
168 | }; | ||
169 | 169 | ||
170 | if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) { | 170 | if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) { |
171 | if let Some(if_expr) = | 171 | if let Some(if_expr) = |