aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libeditor')
-rw-r--r--crates/libeditor/src/completion.rs74
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 { 83fn 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
107fn 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}