diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/libeditor/src/completion.rs | 222 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs | 33 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/mod.rs | 6 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 11 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar/patterns.rs | 2 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar/types.rs | 5 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0018_incomplete_fn.txt | 245 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.rs | 2 | ||||
-rw-r--r-- | crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.txt | 34 | ||||
-rw-r--r-- | crates/server/src/main_loop/handlers.rs | 3 |
10 files changed, 326 insertions, 237 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs index b296f6fd5..6c3775127 100644 --- a/crates/libeditor/src/completion.rs +++ b/crates/libeditor/src/completion.rs | |||
@@ -1,11 +1,11 @@ | |||
1 | use std::collections::HashSet; | 1 | use std::collections::{HashSet, HashMap}; |
2 | 2 | ||
3 | use libsyntax2::{ | 3 | use libsyntax2::{ |
4 | File, TextUnit, AstNode, SyntaxKind::*, | 4 | File, TextUnit, AstNode, SyntaxNodeRef, SyntaxKind::*, |
5 | ast::{self, LoopBodyOwner}, | 5 | ast::{self, LoopBodyOwner}, |
6 | algo::{ | 6 | algo::{ |
7 | ancestors, | 7 | ancestors, |
8 | visit::{visitor, Visitor}, | 8 | visit::{visitor, Visitor, visitor_ctx, VisitorCtx}, |
9 | }, | 9 | }, |
10 | text_utils::is_subrange, | 10 | text_utils::is_subrange, |
11 | }; | 11 | }; |
@@ -17,7 +17,11 @@ use { | |||
17 | 17 | ||
18 | #[derive(Debug)] | 18 | #[derive(Debug)] |
19 | pub struct CompletionItem { | 19 | pub struct CompletionItem { |
20 | pub name: String, | 20 | /// What user sees in pop-up |
21 | pub label: String, | ||
22 | /// What string is used for filtering, defaults to label | ||
23 | pub lookup: Option<String>, | ||
24 | /// What is inserted, defaults to label | ||
21 | pub snippet: Option<String> | 25 | pub snippet: Option<String> |
22 | } | 26 | } |
23 | 27 | ||
@@ -27,40 +31,89 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI | |||
27 | let edit = AtomEdit::insert(offset, "intellijRulezz".to_string()); | 31 | let edit = AtomEdit::insert(offset, "intellijRulezz".to_string()); |
28 | file.reparse(&edit) | 32 | file.reparse(&edit) |
29 | }; | 33 | }; |
30 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?; | 34 | let mut has_completions = false; |
31 | if !is_single_segment(name_ref) { | 35 | let mut res = Vec::new(); |
32 | return None; | 36 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), offset) { |
37 | has_completions = true; | ||
38 | complete_name_ref(&file, name_ref, &mut res) | ||
39 | } | ||
40 | if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), offset) { | ||
41 | has_completions = true; | ||
42 | complete_name(&file, name, &mut res) | ||
43 | } | ||
44 | if has_completions { | ||
45 | Some(res) | ||
46 | } else { | ||
47 | None | ||
33 | } | 48 | } |
49 | } | ||
34 | 50 | ||
35 | let mut res = Vec::new(); | 51 | fn complete_name_ref(file: &File, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) { |
52 | if !is_node::<ast::Path>(name_ref.syntax()) { | ||
53 | return; | ||
54 | } | ||
36 | if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() { | 55 | if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() { |
37 | complete_expr_keywords(&file, fn_def, name_ref, &mut res); | 56 | complete_expr_keywords(&file, fn_def, name_ref, acc); |
38 | let scopes = FnScopes::new(fn_def); | 57 | let scopes = FnScopes::new(fn_def); |
39 | complete_fn(name_ref, &scopes, &mut res); | 58 | complete_fn(name_ref, &scopes, acc); |
40 | } | 59 | } |
41 | if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() { | 60 | if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() { |
42 | let scope = ModuleScope::new(root); | 61 | let scope = ModuleScope::new(root); |
43 | res.extend( | 62 | acc.extend( |
44 | scope.entries().iter() | 63 | scope.entries().iter() |
45 | .filter(|entry| entry.syntax() != name_ref.syntax()) | 64 | .filter(|entry| entry.syntax() != name_ref.syntax()) |
46 | .map(|entry| CompletionItem { | 65 | .map(|entry| CompletionItem { |
47 | name: entry.name().to_string(), | 66 | label: entry.name().to_string(), |
67 | lookup: None, | ||
48 | snippet: None, | 68 | snippet: None, |
49 | }) | 69 | }) |
50 | ); | 70 | ); |
51 | } | 71 | } |
52 | Some(res) | ||
53 | } | 72 | } |
54 | 73 | ||
55 | fn is_single_segment(name_ref: ast::NameRef) -> bool { | 74 | fn complete_name(_file: &File, name: ast::Name, acc: &mut Vec<CompletionItem>) { |
56 | match ancestors(name_ref.syntax()).filter_map(ast::Path::cast).next() { | 75 | if !is_node::<ast::Param>(name.syntax()) { |
76 | return; | ||
77 | } | ||
78 | |||
79 | let mut params = HashMap::new(); | ||
80 | for node in ancestors(name.syntax()) { | ||
81 | let _ = visitor_ctx(&mut params) | ||
82 | .visit::<ast::Root, _>(process) | ||
83 | .accept(node); | ||
84 | } | ||
85 | params.into_iter() | ||
86 | .filter_map(|(label, (count, param))| { | ||
87 | let lookup = param.pat()?.syntax().text().to_string(); | ||
88 | if count < 2 { None } else { Some((label, lookup)) } | ||
89 | }) | ||
90 | .for_each(|(label, lookup)| { | ||
91 | acc.push(CompletionItem { | ||
92 | label, lookup: Some(lookup), snippet: None | ||
93 | }) | ||
94 | }); | ||
95 | |||
96 | fn process<'a, N: ast::FnDefOwner<'a>>(node: N, params: &mut HashMap<String, (u32, ast::Param<'a>)>) { | ||
97 | node.functions() | ||
98 | .filter_map(|it| it.param_list()) | ||
99 | .flat_map(|it| it.params()) | ||
100 | .for_each(|param| { | ||
101 | let text = param.syntax().text().to_string(); | ||
102 | params.entry(text) | ||
103 | .or_insert((0, param)) | ||
104 | .0 += 1; | ||
105 | }) | ||
106 | } | ||
107 | } | ||
108 | |||
109 | fn is_node<'a, N: AstNode<'a>>(node: SyntaxNodeRef<'a>) -> bool { | ||
110 | match ancestors(node).filter_map(N::cast).next() { | ||
57 | None => false, | 111 | None => false, |
58 | Some(path) => { | 112 | Some(n) => n.syntax().range() == node.range(), |
59 | path.syntax().range() == name_ref.syntax().range() | ||
60 | } | ||
61 | } | 113 | } |
62 | } | 114 | } |
63 | 115 | ||
116 | |||
64 | fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) { | 117 | fn complete_expr_keywords(file: &File, fn_def: ast::FnDef, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) { |
65 | acc.push(keyword("if", "if $0 {}")); | 118 | acc.push(keyword("if", "if $0 {}")); |
66 | acc.push(keyword("match", "match $0 {}")); | 119 | acc.push(keyword("match", "match $0 {}")); |
@@ -127,7 +180,8 @@ fn complete_return(fn_def: ast::FnDef, name_ref: ast::NameRef) -> Option<Complet | |||
127 | 180 | ||
128 | fn keyword(kw: &str, snip: &str) -> CompletionItem { | 181 | fn keyword(kw: &str, snip: &str) -> CompletionItem { |
129 | CompletionItem { | 182 | CompletionItem { |
130 | name: kw.to_string(), | 183 | label: kw.to_string(), |
184 | lookup: None, | ||
131 | snippet: Some(snip.to_string()), | 185 | snippet: Some(snip.to_string()), |
132 | } | 186 | } |
133 | } | 187 | } |
@@ -139,13 +193,15 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi | |||
139 | .flat_map(|scope| scopes.entries(scope).iter()) | 193 | .flat_map(|scope| scopes.entries(scope).iter()) |
140 | .filter(|entry| shadowed.insert(entry.name())) | 194 | .filter(|entry| shadowed.insert(entry.name())) |
141 | .map(|entry| CompletionItem { | 195 | .map(|entry| CompletionItem { |
142 | name: entry.name().to_string(), | 196 | label: entry.name().to_string(), |
197 | lookup: None, | ||
143 | snippet: None, | 198 | snippet: None, |
144 | }) | 199 | }) |
145 | ); | 200 | ); |
146 | if scopes.self_param.is_some() { | 201 | if scopes.self_param.is_some() { |
147 | acc.push(CompletionItem { | 202 | acc.push(CompletionItem { |
148 | name: "self".to_string(), | 203 | label: "self".to_string(), |
204 | lookup: None, | ||
149 | snippet: None, | 205 | snippet: None, |
150 | }) | 206 | }) |
151 | } | 207 | } |
@@ -186,9 +242,9 @@ mod tests { | |||
186 | 1 + <|>; | 242 | 1 + <|>; |
187 | let z = (); | 243 | let z = (); |
188 | } | 244 | } |
189 | ", r#"[CompletionItem { name: "y", snippet: None }, | 245 | ", r#"[CompletionItem { label: "y", lookup: None, snippet: None }, |
190 | CompletionItem { name: "x", snippet: None }, | 246 | CompletionItem { label: "x", lookup: None, snippet: None }, |
191 | CompletionItem { name: "quux", snippet: None }]"#); | 247 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#); |
192 | } | 248 | } |
193 | 249 | ||
194 | #[test] | 250 | #[test] |
@@ -203,9 +259,9 @@ mod tests { | |||
203 | 1 + <|> | 259 | 1 + <|> |
204 | } | 260 | } |
205 | } | 261 | } |
206 | ", r#"[CompletionItem { name: "b", snippet: None }, | 262 | ", r#"[CompletionItem { label: "b", lookup: None, snippet: None }, |
207 | CompletionItem { name: "a", snippet: None }, | 263 | CompletionItem { label: "a", lookup: None, snippet: None }, |
208 | CompletionItem { name: "quux", snippet: None }]"#); | 264 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#); |
209 | } | 265 | } |
210 | 266 | ||
211 | #[test] | 267 | #[test] |
@@ -216,8 +272,8 @@ mod tests { | |||
216 | <|> | 272 | <|> |
217 | } | 273 | } |
218 | } | 274 | } |
219 | ", r#"[CompletionItem { name: "x", snippet: None }, | 275 | ", r#"[CompletionItem { label: "x", lookup: None, snippet: None }, |
220 | CompletionItem { name: "quux", snippet: None }]"#); | 276 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#); |
221 | } | 277 | } |
222 | 278 | ||
223 | #[test] | 279 | #[test] |
@@ -228,9 +284,9 @@ mod tests { | |||
228 | fn quux() { | 284 | fn quux() { |
229 | <|> | 285 | <|> |
230 | } | 286 | } |
231 | ", r#"[CompletionItem { name: "Foo", snippet: None }, | 287 | ", r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, |
232 | CompletionItem { name: "Baz", snippet: None }, | 288 | CompletionItem { label: "Baz", lookup: None, snippet: None }, |
233 | CompletionItem { name: "quux", snippet: None }]"#); | 289 | CompletionItem { label: "quux", lookup: None, snippet: None }]"#); |
234 | } | 290 | } |
235 | 291 | ||
236 | #[test] | 292 | #[test] |
@@ -245,8 +301,8 @@ mod tests { | |||
245 | check_scope_completion(r" | 301 | check_scope_completion(r" |
246 | struct Foo; | 302 | struct Foo; |
247 | fn x() -> <|> | 303 | fn x() -> <|> |
248 | ", r#"[CompletionItem { name: "Foo", snippet: None }, | 304 | ", r#"[CompletionItem { label: "Foo", lookup: None, snippet: None }, |
249 | CompletionItem { name: "x", snippet: None }]"#) | 305 | CompletionItem { label: "x", lookup: None, snippet: None }]"#) |
250 | } | 306 | } |
251 | 307 | ||
252 | #[test] | 308 | #[test] |
@@ -259,15 +315,15 @@ mod tests { | |||
259 | <|> | 315 | <|> |
260 | } | 316 | } |
261 | } | 317 | } |
262 | ", r#"[CompletionItem { name: "bar", snippet: None }, | 318 | ", r#"[CompletionItem { label: "bar", lookup: None, snippet: None }, |
263 | CompletionItem { name: "foo", snippet: None }]"#) | 319 | CompletionItem { label: "foo", lookup: None, snippet: None }]"#) |
264 | } | 320 | } |
265 | 321 | ||
266 | #[test] | 322 | #[test] |
267 | fn test_complete_self() { | 323 | fn test_complete_self() { |
268 | check_scope_completion(r" | 324 | check_scope_completion(r" |
269 | impl S { fn foo(&self) { <|> } } | 325 | impl S { fn foo(&self) { <|> } } |
270 | ", r#"[CompletionItem { name: "self", snippet: None }]"#) | 326 | ", r#"[CompletionItem { label: "self", lookup: None, snippet: None }]"#) |
271 | } | 327 | } |
272 | 328 | ||
273 | #[test] | 329 | #[test] |
@@ -276,11 +332,11 @@ mod tests { | |||
276 | fn quux() { | 332 | fn quux() { |
277 | <|> | 333 | <|> |
278 | } | 334 | } |
279 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 335 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
280 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 336 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
281 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 337 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
282 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 338 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
283 | CompletionItem { name: "return", snippet: Some("return") }]"#); | 339 | CompletionItem { label: "return", lookup: None, snippet: Some("return") }]"#); |
284 | } | 340 | } |
285 | 341 | ||
286 | #[test] | 342 | #[test] |
@@ -291,13 +347,13 @@ mod tests { | |||
291 | () | 347 | () |
292 | } <|> | 348 | } <|> |
293 | } | 349 | } |
294 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 350 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
295 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 351 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
296 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 352 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
297 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 353 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
298 | CompletionItem { name: "else", snippet: Some("else {$0}") }, | 354 | CompletionItem { label: "else", lookup: None, snippet: Some("else {$0}") }, |
299 | CompletionItem { name: "else if", snippet: Some("else if $0 {}") }, | 355 | CompletionItem { label: "else if", lookup: None, snippet: Some("else if $0 {}") }, |
300 | CompletionItem { name: "return", snippet: Some("return") }]"#); | 356 | CompletionItem { label: "return", lookup: None, snippet: Some("return") }]"#); |
301 | } | 357 | } |
302 | 358 | ||
303 | #[test] | 359 | #[test] |
@@ -307,21 +363,21 @@ mod tests { | |||
307 | <|> | 363 | <|> |
308 | 92 | 364 | 92 |
309 | } | 365 | } |
310 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 366 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
311 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 367 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
312 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 368 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
313 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 369 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
314 | CompletionItem { name: "return", snippet: Some("return $0;") }]"#); | 370 | CompletionItem { label: "return", lookup: None, snippet: Some("return $0;") }]"#); |
315 | check_snippet_completion(r" | 371 | check_snippet_completion(r" |
316 | fn quux() { | 372 | fn quux() { |
317 | <|> | 373 | <|> |
318 | 92 | 374 | 92 |
319 | } | 375 | } |
320 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 376 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
321 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 377 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
322 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 378 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
323 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 379 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
324 | CompletionItem { name: "return", snippet: Some("return;") }]"#); | 380 | CompletionItem { label: "return", lookup: None, snippet: Some("return;") }]"#); |
325 | } | 381 | } |
326 | 382 | ||
327 | #[test] | 383 | #[test] |
@@ -332,11 +388,11 @@ mod tests { | |||
332 | () => <|> | 388 | () => <|> |
333 | } | 389 | } |
334 | } | 390 | } |
335 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 391 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
336 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 392 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
337 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 393 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
338 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 394 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
339 | CompletionItem { name: "return", snippet: Some("return $0") }]"#); | 395 | CompletionItem { label: "return", lookup: None, snippet: Some("return $0") }]"#); |
340 | } | 396 | } |
341 | 397 | ||
342 | #[test] | 398 | #[test] |
@@ -345,21 +401,35 @@ mod tests { | |||
345 | fn quux() -> i32 { | 401 | fn quux() -> i32 { |
346 | loop { <|> } | 402 | loop { <|> } |
347 | } | 403 | } |
348 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 404 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
349 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 405 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
350 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 406 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
351 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 407 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
352 | CompletionItem { name: "continue", snippet: Some("continue") }, | 408 | CompletionItem { label: "continue", lookup: None, snippet: Some("continue") }, |
353 | CompletionItem { name: "break", snippet: Some("break") }, | 409 | CompletionItem { label: "break", lookup: None, snippet: Some("break") }, |
354 | CompletionItem { name: "return", snippet: Some("return $0") }]"#); | 410 | CompletionItem { label: "return", lookup: None, snippet: Some("return $0") }]"#); |
355 | check_snippet_completion(r" | 411 | check_snippet_completion(r" |
356 | fn quux() -> i32 { | 412 | fn quux() -> i32 { |
357 | loop { || { <|> } } | 413 | loop { || { <|> } } |
358 | } | 414 | } |
359 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 {}") }, | 415 | ", r#"[CompletionItem { label: "if", lookup: None, snippet: Some("if $0 {}") }, |
360 | CompletionItem { name: "match", snippet: Some("match $0 {}") }, | 416 | CompletionItem { label: "match", lookup: None, snippet: Some("match $0 {}") }, |
361 | CompletionItem { name: "while", snippet: Some("while $0 {}") }, | 417 | CompletionItem { label: "while", lookup: None, snippet: Some("while $0 {}") }, |
362 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | 418 | CompletionItem { label: "loop", lookup: None, snippet: Some("loop {$0}") }, |
363 | CompletionItem { name: "return", snippet: Some("return $0") }]"#); | 419 | CompletionItem { label: "return", lookup: None, snippet: Some("return $0") }]"#); |
420 | } | ||
421 | |||
422 | #[test] | ||
423 | fn test_param_completion() { | ||
424 | check_scope_completion(r" | ||
425 | fn foo(file_id: FileId) {} | ||
426 | fn bar(file_id: FileId) {} | ||
427 | fn baz(file<|>) {} | ||
428 | ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); | ||
429 | check_scope_completion(r" | ||
430 | fn foo(file_id: FileId) {} | ||
431 | fn bar(file_id: FileId) {} | ||
432 | fn baz(file<|>, x: i32) {} | ||
433 | ", r#"[CompletionItem { label: "file_id: FileId", lookup: Some("file_id"), snippet: None }]"#); | ||
364 | } | 434 | } |
365 | } | 435 | } |
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 11306a835..4a57837df 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -682,6 +682,28 @@ impl<'a> AstNode<'a> for IndexExpr<'a> { | |||
682 | 682 | ||
683 | impl<'a> IndexExpr<'a> {} | 683 | impl<'a> IndexExpr<'a> {} |
684 | 684 | ||
685 | // ItemList | ||
686 | #[derive(Debug, Clone, Copy)] | ||
687 | pub struct ItemList<'a> { | ||
688 | syntax: SyntaxNodeRef<'a>, | ||
689 | } | ||
690 | |||
691 | impl<'a> AstNode<'a> for ItemList<'a> { | ||
692 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
693 | match syntax.kind() { | ||
694 | ITEM_LIST => Some(ItemList { syntax }), | ||
695 | _ => None, | ||
696 | } | ||
697 | } | ||
698 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
699 | } | ||
700 | |||
701 | impl<'a> ItemList<'a> { | ||
702 | pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { | ||
703 | super::children(self) | ||
704 | } | ||
705 | } | ||
706 | |||
685 | // Label | 707 | // Label |
686 | #[derive(Debug, Clone, Copy)] | 708 | #[derive(Debug, Clone, Copy)] |
687 | pub struct Label<'a> { | 709 | pub struct Label<'a> { |
@@ -956,9 +978,9 @@ impl<'a> AstNode<'a> for Module<'a> { | |||
956 | 978 | ||
957 | impl<'a> ast::NameOwner<'a> for Module<'a> {} | 979 | impl<'a> ast::NameOwner<'a> for Module<'a> {} |
958 | impl<'a> ast::AttrsOwner<'a> for Module<'a> {} | 980 | impl<'a> ast::AttrsOwner<'a> for Module<'a> {} |
959 | impl<'a> Module<'a> { | 981 | impl<'a> ast::FnDefOwner<'a> for Module<'a> {} |
960 | pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { | 982 | impl<'a> Module<'a> {pub fn item_list(self) -> Option<ItemList<'a>> { |
961 | super::children(self) | 983 | super::child_opt(self) |
962 | } | 984 | } |
963 | } | 985 | } |
964 | 986 | ||
@@ -1593,15 +1615,12 @@ impl<'a> AstNode<'a> for Root<'a> { | |||
1593 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | 1615 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } |
1594 | } | 1616 | } |
1595 | 1617 | ||
1618 | impl<'a> ast::FnDefOwner<'a> for Root<'a> {} | ||
1596 | impl<'a> Root<'a> { | 1619 | impl<'a> Root<'a> { |
1597 | pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { | 1620 | pub fn items(self) -> impl Iterator<Item = ModuleItem<'a>> + 'a { |
1598 | super::children(self) | 1621 | super::children(self) |
1599 | } | 1622 | } |
1600 | 1623 | ||
1601 | pub fn functions(self) -> impl Iterator<Item = FnDef<'a>> + 'a { | ||
1602 | super::children(self) | ||
1603 | } | ||
1604 | |||
1605 | pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a { | 1624 | pub fn modules(self) -> impl Iterator<Item = Module<'a>> + 'a { |
1606 | super::children(self) | 1625 | super::children(self) |
1607 | } | 1626 | } |
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index 274996171..881f380f3 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs | |||
@@ -32,6 +32,12 @@ pub trait ArgListOwner<'a>: AstNode<'a> { | |||
32 | } | 32 | } |
33 | } | 33 | } |
34 | 34 | ||
35 | pub trait FnDefOwner<'a>: AstNode<'a> { | ||
36 | fn functions(self) -> Box<Iterator<Item=FnDef<'a>> + 'a> { | ||
37 | Box::new(children(self)) | ||
38 | } | ||
39 | } | ||
40 | |||
35 | pub trait TypeParamsOwner<'a>: AstNode<'a> { | 41 | pub trait TypeParamsOwner<'a>: AstNode<'a> { |
36 | fn type_param_list(self) -> Option<TypeParamList<'a>> { | 42 | fn type_param_list(self) -> Option<TypeParamList<'a>> { |
37 | child_opt(self) | 43 | child_opt(self) |
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index 683623a5d..8a2b780f0 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -238,9 +238,9 @@ Grammar( | |||
238 | ], | 238 | ], |
239 | ast: { | 239 | ast: { |
240 | "Root": ( | 240 | "Root": ( |
241 | traits: [ "FnDefOwner" ], | ||
241 | collections: [ | 242 | collections: [ |
242 | ["items", "ModuleItem"], | 243 | ["items", "ModuleItem"], |
243 | ["functions", "FnDef"], | ||
244 | ["modules", "Module"], | 244 | ["modules", "Module"], |
245 | ] | 245 | ] |
246 | ), | 246 | ), |
@@ -271,10 +271,11 @@ Grammar( | |||
271 | ] ), | 271 | ] ), |
272 | "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ), | 272 | "TraitDef": ( traits: ["NameOwner", "AttrsOwner"] ), |
273 | "Module": ( | 273 | "Module": ( |
274 | traits: ["NameOwner", "AttrsOwner"], | 274 | traits: ["NameOwner", "AttrsOwner", "FnDefOwner" ], |
275 | collections: [ | 275 | options: [ "ItemList" ] |
276 | ["items", "ModuleItem"] | 276 | ), |
277 | ] | 277 | "ItemList": ( |
278 | collections: [ ["items", "ModuleItem"] ] | ||
278 | ), | 279 | ), |
279 | "ConstDef": ( traits: [ | 280 | "ConstDef": ( traits: [ |
280 | "NameOwner", | 281 | "NameOwner", |
diff --git a/crates/libsyntax2/src/grammar/patterns.rs b/crates/libsyntax2/src/grammar/patterns.rs index 065570b99..aa20ae8e4 100644 --- a/crates/libsyntax2/src/grammar/patterns.rs +++ b/crates/libsyntax2/src/grammar/patterns.rs | |||
@@ -23,7 +23,7 @@ pub(super) fn pattern(p: &mut Parser) { | |||
23 | } | 23 | } |
24 | 24 | ||
25 | const PAT_RECOVERY_SET: TokenSet = | 25 | const PAT_RECOVERY_SET: TokenSet = |
26 | token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW]; | 26 | token_set![LET_KW, IF_KW, WHILE_KW, LOOP_KW, MATCH_KW, R_PAREN, COMMA]; |
27 | 27 | ||
28 | 28 | ||
29 | fn atom_pat(p: &mut Parser) -> Option<CompletedMarker> { | 29 | fn atom_pat(p: &mut Parser) -> Option<CompletedMarker> { |
diff --git a/crates/libsyntax2/src/grammar/types.rs b/crates/libsyntax2/src/grammar/types.rs index 89030e66c..a52355b50 100644 --- a/crates/libsyntax2/src/grammar/types.rs +++ b/crates/libsyntax2/src/grammar/types.rs | |||
@@ -8,6 +8,9 @@ pub(super) const TYPE_FIRST: TokenSet = | |||
8 | paths::PATH_FIRST, | 8 | paths::PATH_FIRST, |
9 | ]; | 9 | ]; |
10 | 10 | ||
11 | const TYPE_RECOVERY_SET: TokenSet = | ||
12 | token_set![R_PAREN, COMMA]; | ||
13 | |||
11 | pub(super) fn type_(p: &mut Parser) { | 14 | pub(super) fn type_(p: &mut Parser) { |
12 | match p.current() { | 15 | match p.current() { |
13 | L_PAREN => paren_or_tuple_type(p), | 16 | L_PAREN => paren_or_tuple_type(p), |
@@ -23,7 +26,7 @@ pub(super) fn type_(p: &mut Parser) { | |||
23 | L_ANGLE => path_type(p), | 26 | L_ANGLE => path_type(p), |
24 | _ if paths::is_path_start(p) => path_type(p), | 27 | _ if paths::is_path_start(p) => path_type(p), |
25 | _ => { | 28 | _ => { |
26 | p.err_and_bump("expected type"); | 29 | p.err_recover("expected type", TYPE_RECOVERY_SET); |
27 | } | 30 | } |
28 | } | 31 | } |
29 | } | 32 | } |
diff --git a/crates/libsyntax2/tests/data/parser/err/0018_incomplete_fn.txt b/crates/libsyntax2/tests/data/parser/err/0018_incomplete_fn.txt index 58e39a341..c4d9f5e7e 100644 --- a/crates/libsyntax2/tests/data/parser/err/0018_incomplete_fn.txt +++ b/crates/libsyntax2/tests/data/parser/err/0018_incomplete_fn.txt | |||
@@ -11,168 +11,121 @@ ROOT@[0; 183) | |||
11 | ITEM_LIST@[14; 182) | 11 | ITEM_LIST@[14; 182) |
12 | L_CURLY@[14; 15) | 12 | L_CURLY@[14; 15) |
13 | WHITESPACE@[15; 20) | 13 | WHITESPACE@[15; 20) |
14 | FN_DEF@[20; 180) | 14 | FN_DEF@[20; 161) |
15 | FN_KW@[20; 22) | 15 | FN_KW@[20; 22) |
16 | WHITESPACE@[22; 23) | 16 | WHITESPACE@[22; 23) |
17 | NAME@[23; 32) | 17 | NAME@[23; 32) |
18 | IDENT@[23; 32) "new_scope" | 18 | IDENT@[23; 32) "new_scope" |
19 | PARAM_LIST@[32; 180) | 19 | PARAM_LIST@[32; 35) |
20 | L_PAREN@[32; 33) | 20 | L_PAREN@[32; 33) |
21 | PARAM@[33; 38) | 21 | PARAM@[33; 34) |
22 | REF_PAT@[33; 35) | 22 | REF_PAT@[33; 34) |
23 | AMP@[33; 34) | 23 | AMP@[33; 34) |
24 | err: `expected pattern` | 24 | err: `expected pattern` |
25 | ERROR@[34; 35) | 25 | err: `expected COLON` |
26 | R_PAREN@[34; 35) | 26 | err: `expected type` |
27 | err: `expected COLON` | 27 | R_PAREN@[34; 35) |
28 | WHITESPACE@[35; 36) | 28 | WHITESPACE@[35; 36) |
29 | err: `expected type` | 29 | RET_TYPE@[36; 46) |
30 | ERROR@[36; 38) | 30 | THIN_ARROW@[36; 38) |
31 | THIN_ARROW@[36; 38) | ||
32 | err: `expected COMMA` | ||
33 | WHITESPACE@[38; 39) | 31 | WHITESPACE@[38; 39) |
34 | PARAM@[39; 169) | 32 | PATH_TYPE@[39; 46) |
35 | STRUCT_PAT@[39; 161) | 33 | PATH@[39; 46) |
36 | PATH@[39; 46) | 34 | PATH_SEGMENT@[39; 46) |
37 | PATH_SEGMENT@[39; 46) | 35 | NAME_REF@[39; 46) |
38 | NAME_REF@[39; 46) | 36 | IDENT@[39; 46) "ScopeId" |
39 | IDENT@[39; 46) "ScopeId" | 37 | WHITESPACE@[46; 47) |
40 | WHITESPACE@[46; 47) | 38 | BLOCK@[47; 161) |
41 | FIELD_PAT_LIST@[47; 161) | 39 | L_CURLY@[47; 48) |
42 | L_CURLY@[47; 48) | 40 | WHITESPACE@[48; 57) |
43 | WHITESPACE@[48; 57) | 41 | LET_STMT@[57; 85) |
44 | err: `expected a name` | 42 | LET_KW@[57; 60) |
45 | BIND_PAT@[57; 60) | 43 | WHITESPACE@[60; 61) |
46 | ERROR@[57; 60) | 44 | BIND_PAT@[61; 64) |
47 | LET_KW@[57; 60) | 45 | NAME@[61; 64) |
48 | err: `expected COMMA` | 46 | IDENT@[61; 64) "res" |
49 | WHITESPACE@[60; 61) | 47 | WHITESPACE@[64; 65) |
50 | BIND_PAT@[61; 64) | 48 | EQ@[65; 66) |
51 | NAME@[61; 64) | 49 | WHITESPACE@[66; 67) |
52 | IDENT@[61; 64) "res" | 50 | METHOD_CALL_EXPR@[67; 84) |
53 | err: `expected COMMA` | 51 | FIELD_EXPR@[67; 78) |
54 | WHITESPACE@[64; 65) | 52 | PATH_EXPR@[67; 71) |
55 | err: `expected a name` | 53 | PATH@[67; 71) |
56 | BIND_PAT@[65; 66) | 54 | PATH_SEGMENT@[67; 71) |
57 | ERROR@[65; 66) | 55 | SELF_KW@[67; 71) |
58 | EQ@[65; 66) | 56 | DOT@[71; 72) |
59 | err: `expected COMMA` | 57 | NAME_REF@[72; 78) |
60 | WHITESPACE@[66; 67) | 58 | IDENT@[72; 78) "scopes" |
61 | err: `expected a name` | 59 | DOT@[78; 79) |
62 | BIND_PAT@[67; 71) | 60 | NAME_REF@[79; 82) |
63 | ERROR@[67; 71) | 61 | IDENT@[79; 82) "len" |
64 | SELF_KW@[67; 71) | 62 | ARG_LIST@[82; 84) |
65 | err: `expected COMMA` | 63 | L_PAREN@[82; 83) |
66 | err: `expected a name` | 64 | R_PAREN@[83; 84) |
67 | BIND_PAT@[71; 72) | 65 | SEMI@[84; 85) |
68 | ERROR@[71; 72) | 66 | WHITESPACE@[85; 94) |
69 | DOT@[71; 72) | 67 | METHOD_CALL_EXPR@[94; 155) |
70 | err: `expected COMMA` | 68 | FIELD_EXPR@[94; 105) |
71 | BIND_PAT@[72; 78) | 69 | PATH_EXPR@[94; 98) |
72 | NAME@[72; 78) | 70 | PATH@[94; 98) |
73 | IDENT@[72; 78) "scopes" | 71 | PATH_SEGMENT@[94; 98) |
74 | err: `expected COMMA` | ||
75 | err: `expected a name` | ||
76 | BIND_PAT@[78; 79) | ||
77 | ERROR@[78; 79) | ||
78 | DOT@[78; 79) | ||
79 | err: `expected COMMA` | ||
80 | BIND_PAT@[79; 82) | ||
81 | NAME@[79; 82) | ||
82 | IDENT@[79; 82) "len" | ||
83 | err: `expected COMMA` | ||
84 | err: `expected a name` | ||
85 | BIND_PAT@[82; 83) | ||
86 | ERROR@[82; 83) | ||
87 | L_PAREN@[82; 83) | ||
88 | err: `expected COMMA` | ||
89 | err: `expected a name` | ||
90 | BIND_PAT@[83; 84) | ||
91 | ERROR@[83; 84) | ||
92 | R_PAREN@[83; 84) | ||
93 | err: `expected COMMA` | ||
94 | err: `expected a name` | ||
95 | BIND_PAT@[84; 85) | ||
96 | ERROR@[84; 85) | ||
97 | SEMI@[84; 85) | ||
98 | err: `expected COMMA` | ||
99 | WHITESPACE@[85; 94) | ||
100 | err: `expected a name` | ||
101 | BIND_PAT@[94; 98) | ||
102 | ERROR@[94; 98) | ||
103 | SELF_KW@[94; 98) | 72 | SELF_KW@[94; 98) |
104 | err: `expected COMMA` | 73 | DOT@[98; 99) |
105 | err: `expected a name` | 74 | NAME_REF@[99; 105) |
106 | BIND_PAT@[98; 99) | 75 | IDENT@[99; 105) "scopes" |
107 | ERROR@[98; 99) | 76 | DOT@[105; 106) |
108 | DOT@[98; 99) | 77 | NAME_REF@[106; 110) |
109 | err: `expected COMMA` | 78 | IDENT@[106; 110) "push" |
110 | BIND_PAT@[99; 105) | 79 | ARG_LIST@[110; 155) |
111 | NAME@[99; 105) | 80 | L_PAREN@[110; 111) |
112 | IDENT@[99; 105) "scopes" | 81 | STRUCT_LIT@[111; 154) |
113 | err: `expected COMMA` | 82 | PATH@[111; 120) |
114 | err: `expected a name` | 83 | PATH_SEGMENT@[111; 120) |
115 | BIND_PAT@[105; 106) | 84 | NAME_REF@[111; 120) |
116 | ERROR@[105; 106) | 85 | IDENT@[111; 120) "ScopeData" |
117 | DOT@[105; 106) | ||
118 | err: `expected COMMA` | ||
119 | BIND_PAT@[106; 110) | ||
120 | NAME@[106; 110) | ||
121 | IDENT@[106; 110) "push" | ||
122 | err: `expected COMMA` | ||
123 | err: `expected a name` | ||
124 | BIND_PAT@[110; 111) | ||
125 | ERROR@[110; 111) | ||
126 | L_PAREN@[110; 111) | ||
127 | err: `expected COMMA` | ||
128 | BIND_PAT@[111; 120) | ||
129 | NAME@[111; 120) | ||
130 | IDENT@[111; 120) "ScopeData" | ||
131 | err: `expected COMMA` | ||
132 | WHITESPACE@[120; 121) | 86 | WHITESPACE@[120; 121) |
133 | err: `expected ident` | 87 | NAMED_FIELD_LIST@[121; 154) |
134 | ERROR@[121; 154) | ||
135 | L_CURLY@[121; 122) | 88 | L_CURLY@[121; 122) |
136 | WHITESPACE@[122; 123) | 89 | WHITESPACE@[122; 123) |
137 | IDENT@[123; 129) "parent" | 90 | NAMED_FIELD@[123; 135) |
138 | COLON@[129; 130) | 91 | NAME_REF@[123; 129) |
139 | WHITESPACE@[130; 131) | 92 | IDENT@[123; 129) "parent" |
140 | IDENT@[131; 135) "None" | 93 | COLON@[129; 130) |
94 | WHITESPACE@[130; 131) | ||
95 | PATH_EXPR@[131; 135) | ||
96 | PATH@[131; 135) | ||
97 | PATH_SEGMENT@[131; 135) | ||
98 | NAME_REF@[131; 135) | ||
99 | IDENT@[131; 135) "None" | ||
141 | COMMA@[135; 136) | 100 | COMMA@[135; 136) |
142 | WHITESPACE@[136; 137) | 101 | WHITESPACE@[136; 137) |
143 | IDENT@[137; 144) "entries" | 102 | NAMED_FIELD@[137; 152) |
144 | COLON@[144; 145) | 103 | NAME_REF@[137; 144) |
145 | WHITESPACE@[145; 146) | 104 | IDENT@[137; 144) "entries" |
146 | IDENT@[146; 149) "vec" | 105 | COLON@[144; 145) |
147 | EXCL@[149; 150) | 106 | WHITESPACE@[145; 146) |
148 | L_BRACK@[150; 151) | 107 | MACRO_CALL@[146; 152) |
149 | R_BRACK@[151; 152) | 108 | PATH@[146; 149) |
109 | PATH_SEGMENT@[146; 149) | ||
110 | NAME_REF@[146; 149) | ||
111 | IDENT@[146; 149) "vec" | ||
112 | EXCL@[149; 150) | ||
113 | TOKEN_TREE@[150; 152) | ||
114 | L_BRACK@[150; 151) | ||
115 | R_BRACK@[151; 152) | ||
150 | WHITESPACE@[152; 153) | 116 | WHITESPACE@[152; 153) |
151 | R_CURLY@[153; 154) | 117 | R_CURLY@[153; 154) |
152 | err: `expected COMMA` | 118 | R_PAREN@[154; 155) |
153 | err: `expected a name` | 119 | WHITESPACE@[155; 160) |
154 | BIND_PAT@[154; 155) | 120 | R_CURLY@[160; 161) |
155 | ERROR@[154; 155) | 121 | WHITESPACE@[161; 167) |
156 | R_PAREN@[154; 155) | 122 | FN_DEF@[167; 180) |
157 | WHITESPACE@[155; 160) | 123 | FN_KW@[167; 169) |
158 | R_CURLY@[160; 161) | 124 | WHITESPACE@[169; 170) |
159 | err: `expected COLON` | 125 | NAME@[170; 180) |
160 | WHITESPACE@[161; 167) | 126 | IDENT@[170; 180) "set_parent" |
161 | FN_POINTER_TYPE@[167; 169) | 127 | err: `expected function arguments` |
162 | FN_KW@[167; 169) | 128 | err: `expected a block` |
163 | err: `expected parameters` | ||
164 | err: `expected COMMA` | ||
165 | WHITESPACE@[169; 170) | ||
166 | PARAM@[170; 180) | ||
167 | BIND_PAT@[170; 180) | ||
168 | NAME@[170; 180) | ||
169 | IDENT@[170; 180) "set_parent" | ||
170 | err: `expected COLON` | ||
171 | err: `expected type` | ||
172 | err: `expected COMMA` | ||
173 | err: `expected value parameter` | ||
174 | err: `expected R_PAREN` | ||
175 | err: `expected a block` | ||
176 | WHITESPACE@[180; 181) | 129 | WHITESPACE@[180; 181) |
177 | R_CURLY@[181; 182) | 130 | R_CURLY@[181; 182) |
178 | WHITESPACE@[182; 183) | 131 | WHITESPACE@[182; 183) |
diff --git a/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.rs b/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.rs new file mode 100644 index 000000000..7a6c264f6 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.rs | |||
@@ -0,0 +1,2 @@ | |||
1 | fn foo(x: i32, y) { | ||
2 | } | ||
diff --git a/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.txt b/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.txt new file mode 100644 index 000000000..8dcb58ae2 --- /dev/null +++ b/crates/libsyntax2/tests/data/parser/err/0021_incomplete_param.txt | |||
@@ -0,0 +1,34 @@ | |||
1 | ROOT@[0; 22) | ||
2 | FN_DEF@[0; 21) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 17) | ||
8 | L_PAREN@[6; 7) | ||
9 | PARAM@[7; 13) | ||
10 | BIND_PAT@[7; 8) | ||
11 | NAME@[7; 8) | ||
12 | IDENT@[7; 8) "x" | ||
13 | COLON@[8; 9) | ||
14 | WHITESPACE@[9; 10) | ||
15 | PATH_TYPE@[10; 13) | ||
16 | PATH@[10; 13) | ||
17 | PATH_SEGMENT@[10; 13) | ||
18 | NAME_REF@[10; 13) | ||
19 | IDENT@[10; 13) "i32" | ||
20 | COMMA@[13; 14) | ||
21 | WHITESPACE@[14; 15) | ||
22 | PARAM@[15; 16) | ||
23 | BIND_PAT@[15; 16) | ||
24 | NAME@[15; 16) | ||
25 | IDENT@[15; 16) "y" | ||
26 | err: `expected COLON` | ||
27 | err: `expected type` | ||
28 | R_PAREN@[16; 17) | ||
29 | WHITESPACE@[17; 18) | ||
30 | BLOCK@[18; 21) | ||
31 | L_CURLY@[18; 19) | ||
32 | WHITESPACE@[19; 20) | ||
33 | R_CURLY@[20; 21) | ||
34 | WHITESPACE@[21; 22) | ||
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index 93d8bd9fe..898195f6d 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs | |||
@@ -345,7 +345,8 @@ pub fn handle_completion( | |||
345 | let items = items.into_iter() | 345 | let items = items.into_iter() |
346 | .map(|item| { | 346 | .map(|item| { |
347 | let mut res = CompletionItem { | 347 | let mut res = CompletionItem { |
348 | label: item.name, | 348 | label: item.label, |
349 | filter_text: item.lookup, | ||
349 | .. Default::default() | 350 | .. Default::default() |
350 | }; | 351 | }; |
351 | if let Some(snip) = item.snippet { | 352 | if let Some(snip) = item.snippet { |