diff options
-rw-r--r-- | crates/libeditor/src/completion.rs | 74 |
1 files changed, 59 insertions, 15 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs index cfb1c0d1b..fe4c9b217 100644 --- a/crates/libeditor/src/completion.rs +++ b/crates/libeditor/src/completion.rs | |||
@@ -76,18 +76,38 @@ fn complete_keywords(file: &File, fn_def: Option<ast::FnDef>, name_ref: ast::Nam | |||
76 | } | 76 | } |
77 | 77 | ||
78 | if let Some(fn_def) = fn_def { | 78 | if let Some(fn_def) = fn_def { |
79 | if fn_def.ret_type().is_some() { | 79 | acc.extend(complete_return(fn_def, name_ref)); |
80 | acc.push(keyword("return", "return $0;")) | ||
81 | } else { | ||
82 | acc.push(keyword("return", "return;")) | ||
83 | } | ||
84 | } | 80 | } |
81 | } | ||
85 | 82 | ||
86 | fn keyword(kw: &str, snip: &str) -> CompletionItem { | 83 | fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<CompletionItem> { |
87 | CompletionItem { | 84 | let is_last_in_block = ancestors(name_ref.syntax()).filter_map(ast::Expr::cast) |
88 | name: kw.to_string(), | 85 | .next() |
89 | snippet: Some(snip.to_string()), | 86 | .and_then(|it| it.syntax().parent()) |
90 | } | 87 | .and_then(ast::Block::cast) |
88 | .is_some(); | ||
89 | |||
90 | if is_last_in_block { | ||
91 | return None; | ||
92 | } | ||
93 | |||
94 | let is_stmt = match ancestors(name_ref.syntax()).filter_map(ast::ExprStmt::cast).next() { | ||
95 | None => false, | ||
96 | Some(expr_stmt) => expr_stmt.syntax().range() == name_ref.syntax().range() | ||
97 | }; | ||
98 | let snip = match (is_stmt, fn_def.ret_type().is_some()) { | ||
99 | (true, true) => "return $0;", | ||
100 | (true, false) => "return;", | ||
101 | (false, true) => "return $0", | ||
102 | (false, false) => "return", | ||
103 | }; | ||
104 | Some(keyword("return", snip)) | ||
105 | } | ||
106 | |||
107 | fn keyword(kw: &str, snip: &str) -> CompletionItem { | ||
108 | CompletionItem { | ||
109 | name: kw.to_string(), | ||
110 | snippet: Some(snip.to_string()), | ||
91 | } | 111 | } |
92 | } | 112 | } |
93 | 113 | ||
@@ -193,8 +213,7 @@ mod tests { | |||
193 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | 213 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, |
194 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | 214 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, |
195 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | 215 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, |
196 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 216 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }]"#); |
197 | CompletionItem { name: "return", snippet: Some("return;") }]"#); | ||
198 | } | 217 | } |
199 | 218 | ||
200 | #[test] | 219 | #[test] |
@@ -210,20 +229,45 @@ mod tests { | |||
210 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | 229 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, |
211 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 230 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, |
212 | CompletionItem { name: "else", snippet: Some("else {$0}") }, | 231 | CompletionItem { name: "else", snippet: Some("else {$0}") }, |
213 | CompletionItem { name: "else if", snippet: Some("else if $0 { }") }, | 232 | CompletionItem { name: "else if", snippet: Some("else if $0 { }") }]"#); |
214 | CompletionItem { name: "return", snippet: Some("return;") }]"#); | ||
215 | } | 233 | } |
216 | 234 | ||
217 | #[test] | 235 | #[test] |
218 | fn test_completion_return_value() { | 236 | fn test_completion_return_value() { |
219 | check_snippet_completion(r" | 237 | check_snippet_completion(r" |
220 | fn quux() -> i32{ | 238 | fn quux() -> i32 { |
221 | <|> | 239 | <|> |
240 | 92 | ||
222 | } | 241 | } |
223 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | 242 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, |
224 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | 243 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, |
225 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | 244 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, |
226 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 245 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, |
227 | CompletionItem { name: "return", snippet: Some("return $0;") }]"#); | 246 | CompletionItem { name: "return", snippet: Some("return $0;") }]"#); |
247 | check_snippet_completion(r" | ||
248 | fn quux() { | ||
249 | <|> | ||
250 | 92 | ||
251 | } | ||
252 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | ||
253 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | ||
254 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | ||
255 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | ||
256 | CompletionItem { name: "return", snippet: Some("return;") }]"#); | ||
257 | } | ||
258 | |||
259 | #[test] | ||
260 | fn test_completion_return_no_stmt() { | ||
261 | check_snippet_completion(r" | ||
262 | fn quux() -> i32 { | ||
263 | match () { | ||
264 | () => <|> | ||
265 | } | ||
266 | } | ||
267 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | ||
268 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | ||
269 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | ||
270 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | ||
271 | CompletionItem { name: "return", snippet: Some("return $0") }]"#); | ||
228 | } | 272 | } |
229 | } | 273 | } |