diff options
author | Aleksey Kladov <[email protected]> | 2018-08-28 19:11:17 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-28 19:11:17 +0100 |
commit | 2257c08cb159a30492bf2aec172539b1dd504700 (patch) | |
tree | 3346d52224b9444e975314e1af32f4490baf91c2 | |
parent | b00a4d43ecd4af49a2870718a9d5b8d49084a285 (diff) |
Add ret type
14 files changed, 208 insertions, 77 deletions
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs index 7e8669822..65527db62 100644 --- a/crates/libeditor/src/completion.rs +++ b/crates/libeditor/src/completion.rs | |||
@@ -12,7 +12,8 @@ use { | |||
12 | }; | 12 | }; |
13 | 13 | ||
14 | #[derive(Debug)] | 14 | #[derive(Debug)] |
15 | pub struct CompletionItem { | 15 | pub struct |
16 | CompletionItem { | ||
16 | pub name: String, | 17 | pub name: String, |
17 | pub snippet: Option<String> | 18 | pub snippet: Option<String> |
18 | } | 19 | } |
@@ -25,10 +26,17 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI | |||
25 | file.incremental_reparse(&edit)? | 26 | file.incremental_reparse(&edit)? |
26 | }; | 27 | }; |
27 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?; | 28 | let name_ref = find_node_at_offset::<ast::NameRef>(file.syntax(), offset)?; |
29 | if !is_ident_expr(name_ref) { | ||
30 | return None; | ||
31 | } | ||
32 | |||
28 | let mut res = Vec::new(); | 33 | let mut res = Vec::new(); |
29 | if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() { | 34 | if let Some(fn_def) = ancestors(name_ref.syntax()).filter_map(ast::FnDef::cast).next() { |
35 | complete_keywords(&file, Some(fn_def), name_ref, &mut res); | ||
30 | let scopes = FnScopes::new(fn_def); | 36 | let scopes = FnScopes::new(fn_def); |
31 | complete_fn(name_ref, &scopes, &mut res); | 37 | complete_fn(name_ref, &scopes, &mut res); |
38 | } else { | ||
39 | complete_keywords(&file, None, name_ref, &mut res); | ||
32 | } | 40 | } |
33 | if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() { | 41 | if let Some(root) = ancestors(name_ref.syntax()).filter_map(ast::Root::cast).next() { |
34 | let scope = ModuleScope::new(root); | 42 | let scope = ModuleScope::new(root); |
@@ -43,6 +51,42 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI | |||
43 | Some(res) | 51 | Some(res) |
44 | } | 52 | } |
45 | 53 | ||
54 | fn is_ident_expr(name_ref: ast::NameRef) -> bool { | ||
55 | match ancestors(name_ref.syntax()).filter_map(ast::Expr::cast).next() { | ||
56 | None => false, | ||
57 | Some(expr) => { | ||
58 | expr.syntax().range() == name_ref.syntax().range() | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | fn complete_keywords(file: &File, fn_def: Option<ast::FnDef>, name_ref: ast::NameRef, acc: &mut Vec<CompletionItem>) { | ||
64 | acc.push(keyword("if", "if $0 { }")); | ||
65 | acc.push(keyword("match", "match $0 { }")); | ||
66 | acc.push(keyword("while", "while $0 { }")); | ||
67 | acc.push(keyword("loop", "loop {$0}")); | ||
68 | |||
69 | if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) { | ||
70 | if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) { | ||
71 | if if_expr.syntax().range().end() < name_ref.syntax().range().start() { | ||
72 | acc.push(keyword("else", "else {$0}")); | ||
73 | acc.push(keyword("else if", "else if $0 { }")); | ||
74 | } | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // if let Some(fn_def) = fn_def { | ||
79 | // acc.push(keyword("return", "")) | ||
80 | // } | ||
81 | |||
82 | fn keyword(kw: &str, snip: &str) -> CompletionItem { | ||
83 | CompletionItem { | ||
84 | name: kw.to_string(), | ||
85 | snippet: Some(snip.to_string()), | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | |||
46 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { | 90 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { |
47 | acc.extend( | 91 | acc.extend( |
48 | scopes.scope_chain(name_ref.syntax()) | 92 | scopes.scope_chain(name_ref.syntax()) |
@@ -59,29 +103,44 @@ mod tests { | |||
59 | use super::*; | 103 | use super::*; |
60 | use test_utils::{assert_eq_dbg, extract_offset}; | 104 | use test_utils::{assert_eq_dbg, extract_offset}; |
61 | 105 | ||
62 | fn do_check(code: &str, expected_completions: &str) { | 106 | fn check_scope_completion(code: &str, expected_completions: &str) { |
63 | let (off, code) = extract_offset(&code); | 107 | let (off, code) = extract_offset(&code); |
64 | let file = File::parse(&code); | 108 | let file = File::parse(&code); |
65 | let completions = scope_completion(&file, off).unwrap(); | 109 | let completions = scope_completion(&file, off) |
110 | .unwrap() | ||
111 | .into_iter() | ||
112 | .filter(|c| c.snippet.is_none()) | ||
113 | .collect::<Vec<_>>(); | ||
114 | assert_eq_dbg(expected_completions, &completions); | ||
115 | } | ||
116 | |||
117 | fn check_snippet_completion(code: &str, expected_completions: &str) { | ||
118 | let (off, code) = extract_offset(&code); | ||
119 | let file = File::parse(&code); | ||
120 | let completions = scope_completion(&file, off) | ||
121 | .unwrap() | ||
122 | .into_iter() | ||
123 | .filter(|c| c.snippet.is_some()) | ||
124 | .collect::<Vec<_>>(); | ||
66 | assert_eq_dbg(expected_completions, &completions); | 125 | assert_eq_dbg(expected_completions, &completions); |
67 | } | 126 | } |
68 | 127 | ||
69 | #[test] | 128 | #[test] |
70 | fn test_completion_let_scope() { | 129 | fn test_completion_let_scope() { |
71 | do_check(r" | 130 | check_scope_completion(r" |
72 | fn quux(x: i32) { | 131 | fn quux(x: i32) { |
73 | let y = 92; | 132 | let y = 92; |
74 | 1 + <|>; | 133 | 1 + <|>; |
75 | let z = (); | 134 | let z = (); |
76 | } | 135 | } |
77 | ", r#"[CompletionItem { name: "y" }, | 136 | ", r#"[CompletionItem { name: "y", snippet: None }, |
78 | CompletionItem { name: "x" }, | 137 | CompletionItem { name: "x", snippet: None }, |
79 | CompletionItem { name: "quux" }]"#); | 138 | CompletionItem { name: "quux", snippet: None }]"#); |
80 | } | 139 | } |
81 | 140 | ||
82 | #[test] | 141 | #[test] |
83 | fn test_completion_if_let_scope() { | 142 | fn test_completion_if_let_scope() { |
84 | do_check(r" | 143 | check_scope_completion(r" |
85 | fn quux() { | 144 | fn quux() { |
86 | if let Some(x) = foo() { | 145 | if let Some(x) = foo() { |
87 | let y = 92; | 146 | let y = 92; |
@@ -91,33 +150,61 @@ mod tests { | |||
91 | 1 + <|> | 150 | 1 + <|> |
92 | } | 151 | } |
93 | } | 152 | } |
94 | ", r#"[CompletionItem { name: "b" }, | 153 | ", r#"[CompletionItem { name: "b", snippet: None }, |
95 | CompletionItem { name: "a" }, | 154 | CompletionItem { name: "a", snippet: None }, |
96 | CompletionItem { name: "quux" }]"#); | 155 | CompletionItem { name: "quux", snippet: None }]"#); |
97 | } | 156 | } |
98 | 157 | ||
99 | #[test] | 158 | #[test] |
100 | fn test_completion_for_scope() { | 159 | fn test_completion_for_scope() { |
101 | do_check(r" | 160 | check_scope_completion(r" |
102 | fn quux() { | 161 | fn quux() { |
103 | for x in &[1, 2, 3] { | 162 | for x in &[1, 2, 3] { |
104 | <|> | 163 | <|> |
105 | } | 164 | } |
106 | } | 165 | } |
107 | ", r#"[CompletionItem { name: "x" }, | 166 | ", r#"[CompletionItem { name: "x", snippet: None }, |
108 | CompletionItem { name: "quux" }]"#); | 167 | CompletionItem { name: "quux", snippet: None }]"#); |
109 | } | 168 | } |
110 | 169 | ||
111 | #[test] | 170 | #[test] |
112 | fn test_completion_mod_scope() { | 171 | fn test_completion_mod_scope() { |
113 | do_check(r" | 172 | check_scope_completion(r" |
114 | struct Foo; | 173 | struct Foo; |
115 | enum Baz {} | 174 | enum Baz {} |
116 | fn quux() { | 175 | fn quux() { |
117 | <|> | 176 | <|> |
118 | } | 177 | } |
119 | ", r#"[CompletionItem { name: "Foo" }, | 178 | ", r#"[CompletionItem { name: "Foo", snippet: None }, |
120 | CompletionItem { name: "Baz" }, | 179 | CompletionItem { name: "Baz", snippet: None }, |
121 | CompletionItem { name: "quux" }]"#); | 180 | CompletionItem { name: "quux", snippet: None }]"#); |
181 | } | ||
182 | |||
183 | #[test] | ||
184 | fn test_completion_kewords() { | ||
185 | check_snippet_completion(r" | ||
186 | fn quux() { | ||
187 | <|> | ||
188 | } | ||
189 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | ||
190 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | ||
191 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | ||
192 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }]"#); | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn test_completion_else() { | ||
197 | check_snippet_completion(r" | ||
198 | fn quux() { | ||
199 | if true { | ||
200 | () | ||
201 | } <|> | ||
202 | } | ||
203 | ", r#"[CompletionItem { name: "if", snippet: Some("if $0 { }") }, | ||
204 | CompletionItem { name: "match", snippet: Some("match $0 { }") }, | ||
205 | CompletionItem { name: "while", snippet: Some("while $0 { }") }, | ||
206 | CompletionItem { name: "loop", snippet: Some("loop {$0}") }, | ||
207 | CompletionItem { name: "else", snippet: Some("else {$0}") }, | ||
208 | CompletionItem { name: "else if", snippet: Some("else if $0 { }") }]"#); | ||
122 | } | 209 | } |
123 | } | 210 | } |
diff --git a/crates/libsyntax2/Cargo.toml b/crates/libsyntax2/Cargo.toml index 918c02775..3e5a83290 100644 --- a/crates/libsyntax2/Cargo.toml +++ b/crates/libsyntax2/Cargo.toml | |||
@@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" | |||
6 | 6 | ||
7 | [dependencies] | 7 | [dependencies] |
8 | unicode-xid = "0.1.0" | 8 | unicode-xid = "0.1.0" |
9 | text_unit = "0.1.3" | 9 | text_unit = "0.1.4" |
10 | itertools = "0.7.8" | 10 | itertools = "0.7.8" |
11 | drop_bomb = "0.1.4" | 11 | drop_bomb = "0.1.4" |
12 | parking_lot = "0.6.0" | 12 | parking_lot = "0.6.0" |
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 999023e3d..e8743caa8 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -523,6 +523,10 @@ impl<'a> FnDef<'a> { | |||
523 | pub fn body(self) -> Option<Block<'a>> { | 523 | pub fn body(self) -> Option<Block<'a>> { |
524 | super::child_opt(self) | 524 | super::child_opt(self) |
525 | } | 525 | } |
526 | |||
527 | pub fn ret_type(self) -> Option<RetType<'a>> { | ||
528 | super::child_opt(self) | ||
529 | } | ||
526 | } | 530 | } |
527 | 531 | ||
528 | // FnPointerType | 532 | // FnPointerType |
@@ -1412,6 +1416,24 @@ impl<'a> AstNode<'a> for ReferenceType<'a> { | |||
1412 | 1416 | ||
1413 | impl<'a> ReferenceType<'a> {} | 1417 | impl<'a> ReferenceType<'a> {} |
1414 | 1418 | ||
1419 | // RetType | ||
1420 | #[derive(Debug, Clone, Copy)] | ||
1421 | pub struct RetType<'a> { | ||
1422 | syntax: SyntaxNodeRef<'a>, | ||
1423 | } | ||
1424 | |||
1425 | impl<'a> AstNode<'a> for RetType<'a> { | ||
1426 | fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> { | ||
1427 | match syntax.kind() { | ||
1428 | RET_TYPE => Some(RetType { syntax }), | ||
1429 | _ => None, | ||
1430 | } | ||
1431 | } | ||
1432 | fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } | ||
1433 | } | ||
1434 | |||
1435 | impl<'a> RetType<'a> {} | ||
1436 | |||
1415 | // ReturnExpr | 1437 | // ReturnExpr |
1416 | #[derive(Debug, Clone, Copy)] | 1438 | #[derive(Debug, Clone, Copy)] |
1417 | pub struct ReturnExpr<'a> { | 1439 | pub struct ReturnExpr<'a> { |
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index f8fa7b694..f1907d1ce 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -119,6 +119,7 @@ Grammar( | |||
119 | "STRUCT_DEF", | 119 | "STRUCT_DEF", |
120 | "ENUM_DEF", | 120 | "ENUM_DEF", |
121 | "FN_DEF", | 121 | "FN_DEF", |
122 | "RET_TYPE", | ||
122 | "EXTERN_CRATE_ITEM", | 123 | "EXTERN_CRATE_ITEM", |
123 | "MODULE", | 124 | "MODULE", |
124 | "USE_ITEM", | 125 | "USE_ITEM", |
@@ -252,8 +253,10 @@ Grammar( | |||
252 | options: [ | 253 | options: [ |
253 | ["param_list", "ParamList"], | 254 | ["param_list", "ParamList"], |
254 | ["body", "Block"], | 255 | ["body", "Block"], |
256 | ["ret_type", "RetType"] | ||
255 | ], | 257 | ], |
256 | ), | 258 | ), |
259 | "RetType": (), | ||
257 | "StructDef": ( | 260 | "StructDef": ( |
258 | traits: [ | 261 | traits: [ |
259 | "NameOwner", | 262 | "NameOwner", |
diff --git a/crates/libsyntax2/src/grammar/mod.rs b/crates/libsyntax2/src/grammar/mod.rs index 496d28349..1acecac41 100644 --- a/crates/libsyntax2/src/grammar/mod.rs +++ b/crates/libsyntax2/src/grammar/mod.rs | |||
@@ -119,8 +119,10 @@ fn abi(p: &mut Parser) { | |||
119 | 119 | ||
120 | fn opt_fn_ret_type(p: &mut Parser) -> bool { | 120 | fn opt_fn_ret_type(p: &mut Parser) -> bool { |
121 | if p.at(THIN_ARROW) { | 121 | if p.at(THIN_ARROW) { |
122 | let m = p.start(); | ||
122 | p.bump(); | 123 | p.bump(); |
123 | types::type_(p); | 124 | types::type_(p); |
125 | m.complete(p, RET_TYPE); | ||
124 | true | 126 | true |
125 | } else { | 127 | } else { |
126 | false | 128 | false |
diff --git a/crates/libsyntax2/src/syntax_kinds/generated.rs b/crates/libsyntax2/src/syntax_kinds/generated.rs index 0a22b11c2..7882bded9 100644 --- a/crates/libsyntax2/src/syntax_kinds/generated.rs +++ b/crates/libsyntax2/src/syntax_kinds/generated.rs | |||
@@ -119,6 +119,7 @@ pub enum SyntaxKind { | |||
119 | STRUCT_DEF, | 119 | STRUCT_DEF, |
120 | ENUM_DEF, | 120 | ENUM_DEF, |
121 | FN_DEF, | 121 | FN_DEF, |
122 | RET_TYPE, | ||
122 | EXTERN_CRATE_ITEM, | 123 | EXTERN_CRATE_ITEM, |
123 | MODULE, | 124 | MODULE, |
124 | USE_ITEM, | 125 | USE_ITEM, |
@@ -380,6 +381,7 @@ impl SyntaxKind { | |||
380 | STRUCT_DEF => &SyntaxInfo { name: "STRUCT_DEF" }, | 381 | STRUCT_DEF => &SyntaxInfo { name: "STRUCT_DEF" }, |
381 | ENUM_DEF => &SyntaxInfo { name: "ENUM_DEF" }, | 382 | ENUM_DEF => &SyntaxInfo { name: "ENUM_DEF" }, |
382 | FN_DEF => &SyntaxInfo { name: "FN_DEF" }, | 383 | FN_DEF => &SyntaxInfo { name: "FN_DEF" }, |
384 | RET_TYPE => &SyntaxInfo { name: "RET_TYPE" }, | ||
383 | EXTERN_CRATE_ITEM => &SyntaxInfo { name: "EXTERN_CRATE_ITEM" }, | 385 | EXTERN_CRATE_ITEM => &SyntaxInfo { name: "EXTERN_CRATE_ITEM" }, |
384 | MODULE => &SyntaxInfo { name: "MODULE" }, | 386 | MODULE => &SyntaxInfo { name: "MODULE" }, |
385 | USE_ITEM => &SyntaxInfo { name: "USE_ITEM" }, | 387 | USE_ITEM => &SyntaxInfo { name: "USE_ITEM" }, |
diff --git a/crates/libsyntax2/tests/data/parser/err/0010_unsafe_lambda_block.txt b/crates/libsyntax2/tests/data/parser/err/0010_unsafe_lambda_block.txt index 400442c51..edd801599 100644 --- a/crates/libsyntax2/tests/data/parser/err/0010_unsafe_lambda_block.txt +++ b/crates/libsyntax2/tests/data/parser/err/0010_unsafe_lambda_block.txt | |||
@@ -17,13 +17,14 @@ ROOT@[0; 42) | |||
17 | PIPE@[16; 17) | 17 | PIPE@[16; 17) |
18 | PIPE@[17; 18) | 18 | PIPE@[17; 18) |
19 | WHITESPACE@[18; 19) | 19 | WHITESPACE@[18; 19) |
20 | THIN_ARROW@[19; 21) | 20 | RET_TYPE@[19; 24) |
21 | WHITESPACE@[21; 22) | 21 | THIN_ARROW@[19; 21) |
22 | TUPLE_TYPE@[22; 24) | 22 | WHITESPACE@[21; 22) |
23 | L_PAREN@[22; 23) | 23 | TUPLE_TYPE@[22; 24) |
24 | R_PAREN@[23; 24) | 24 | L_PAREN@[22; 23) |
25 | err: `expected a block` | 25 | R_PAREN@[23; 24) |
26 | err: `expected SEMI` | 26 | err: `expected a block` |
27 | err: `expected SEMI` | ||
27 | WHITESPACE@[24; 25) | 28 | WHITESPACE@[24; 25) |
28 | EXPR_STMT@[25; 39) | 29 | EXPR_STMT@[25; 39) |
29 | BLOCK_EXPR@[25; 38) | 30 | BLOCK_EXPR@[25; 38) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt b/crates/libsyntax2/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt index 7d0ecfbd1..203839636 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0030_fn_pointer_type_with_ret.txt | |||
@@ -13,10 +13,11 @@ ROOT@[0; 21) | |||
13 | L_PAREN@[11; 12) | 13 | L_PAREN@[11; 12) |
14 | R_PAREN@[12; 13) | 14 | R_PAREN@[12; 13) |
15 | WHITESPACE@[13; 14) | 15 | WHITESPACE@[13; 14) |
16 | THIN_ARROW@[14; 16) | 16 | RET_TYPE@[14; 19) |
17 | WHITESPACE@[16; 17) | 17 | THIN_ARROW@[14; 16) |
18 | TUPLE_TYPE@[17; 19) | 18 | WHITESPACE@[16; 17) |
19 | L_PAREN@[17; 18) | 19 | TUPLE_TYPE@[17; 19) |
20 | R_PAREN@[18; 19) | 20 | L_PAREN@[17; 18) |
21 | R_PAREN@[18; 19) | ||
21 | SEMI@[19; 20) | 22 | SEMI@[19; 20) |
22 | WHITESPACE@[20; 21) | 23 | WHITESPACE@[20; 21) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0031_for_type.txt b/crates/libsyntax2/tests/data/parser/inline/0031_for_type.txt index 41461f2a6..f6b962b2c 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0031_for_type.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0031_for_type.txt | |||
@@ -21,10 +21,11 @@ ROOT@[0; 29) | |||
21 | L_PAREN@[19; 20) | 21 | L_PAREN@[19; 20) |
22 | R_PAREN@[20; 21) | 22 | R_PAREN@[20; 21) |
23 | WHITESPACE@[21; 22) | 23 | WHITESPACE@[21; 22) |
24 | THIN_ARROW@[22; 24) | 24 | RET_TYPE@[22; 27) |
25 | WHITESPACE@[24; 25) | 25 | THIN_ARROW@[22; 24) |
26 | TUPLE_TYPE@[25; 27) | 26 | WHITESPACE@[24; 25) |
27 | L_PAREN@[25; 26) | 27 | TUPLE_TYPE@[25; 27) |
28 | R_PAREN@[26; 27) | 28 | L_PAREN@[25; 26) |
29 | R_PAREN@[26; 27) | ||
29 | SEMI@[27; 28) | 30 | SEMI@[27; 28) |
30 | WHITESPACE@[28; 29) | 31 | WHITESPACE@[28; 29) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0038_function_ret_type.txt b/crates/libsyntax2/tests/data/parser/inline/0038_function_ret_type.txt index 0df6c8f51..a3d235ce1 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0038_function_ret_type.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0038_function_ret_type.txt | |||
@@ -21,11 +21,12 @@ ROOT@[0; 30) | |||
21 | L_PAREN@[18; 19) | 21 | L_PAREN@[18; 19) |
22 | R_PAREN@[19; 20) | 22 | R_PAREN@[19; 20) |
23 | WHITESPACE@[20; 21) | 23 | WHITESPACE@[20; 21) |
24 | THIN_ARROW@[21; 23) | 24 | RET_TYPE@[21; 26) |
25 | WHITESPACE@[23; 24) | 25 | THIN_ARROW@[21; 23) |
26 | TUPLE_TYPE@[24; 26) | 26 | WHITESPACE@[23; 24) |
27 | L_PAREN@[24; 25) | 27 | TUPLE_TYPE@[24; 26) |
28 | R_PAREN@[25; 26) | 28 | L_PAREN@[24; 25) |
29 | R_PAREN@[25; 26) | ||
29 | WHITESPACE@[26; 27) | 30 | WHITESPACE@[26; 27) |
30 | BLOCK@[27; 29) | 31 | BLOCK@[27; 29) |
31 | L_CURLY@[27; 28) | 32 | L_CURLY@[27; 28) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0066_lambda_expr.txt b/crates/libsyntax2/tests/data/parser/inline/0066_lambda_expr.txt index 6b34bc302..6f8304db3 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0066_lambda_expr.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0066_lambda_expr.txt | |||
@@ -28,13 +28,14 @@ ROOT@[0; 79) | |||
28 | PIPE@[26; 27) | 28 | PIPE@[26; 27) |
29 | PIPE@[27; 28) | 29 | PIPE@[27; 28) |
30 | WHITESPACE@[28; 29) | 30 | WHITESPACE@[28; 29) |
31 | THIN_ARROW@[29; 31) | 31 | RET_TYPE@[29; 35) |
32 | WHITESPACE@[31; 32) | 32 | THIN_ARROW@[29; 31) |
33 | PATH_TYPE@[32; 35) | 33 | WHITESPACE@[31; 32) |
34 | PATH@[32; 35) | 34 | PATH_TYPE@[32; 35) |
35 | PATH_SEGMENT@[32; 35) | 35 | PATH@[32; 35) |
36 | NAME_REF@[32; 35) | 36 | PATH_SEGMENT@[32; 35) |
37 | IDENT@[32; 35) "i32" | 37 | NAME_REF@[32; 35) |
38 | IDENT@[32; 35) "i32" | ||
38 | WHITESPACE@[35; 36) | 39 | WHITESPACE@[35; 36) |
39 | BLOCK@[36; 42) | 40 | BLOCK@[36; 42) |
40 | L_CURLY@[36; 37) | 41 | L_CURLY@[36; 37) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0093_path_fn_trait_args.txt b/crates/libsyntax2/tests/data/parser/inline/0093_path_fn_trait_args.txt index 1b1a8a9e2..26a690d3a 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0093_path_fn_trait_args.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0093_path_fn_trait_args.txt | |||
@@ -35,11 +35,12 @@ ROOT@[0; 32) | |||
35 | IDENT@[19; 22) "i32" | 35 | IDENT@[19; 22) "i32" |
36 | R_PAREN@[22; 23) | 36 | R_PAREN@[22; 23) |
37 | WHITESPACE@[23; 24) | 37 | WHITESPACE@[23; 24) |
38 | THIN_ARROW@[24; 26) | 38 | RET_TYPE@[24; 29) |
39 | WHITESPACE@[26; 27) | 39 | THIN_ARROW@[24; 26) |
40 | TUPLE_TYPE@[27; 29) | 40 | WHITESPACE@[26; 27) |
41 | L_PAREN@[27; 28) | 41 | TUPLE_TYPE@[27; 29) |
42 | R_PAREN@[28; 29) | 42 | L_PAREN@[27; 28) |
43 | R_PAREN@[28; 29) | ||
43 | R_ANGLE@[29; 30) | 44 | R_ANGLE@[29; 30) |
44 | SEMI@[30; 31) | 45 | SEMI@[30; 31) |
45 | WHITESPACE@[31; 32) | 46 | WHITESPACE@[31; 32) |
diff --git a/crates/libsyntax2/tests/data/parser/inline/0095_path_type_with_bounds.txt b/crates/libsyntax2/tests/data/parser/inline/0095_path_type_with_bounds.txt index 0703d1da2..4b864f741 100644 --- a/crates/libsyntax2/tests/data/parser/inline/0095_path_type_with_bounds.txt +++ b/crates/libsyntax2/tests/data/parser/inline/0095_path_type_with_bounds.txt | |||
@@ -8,26 +8,27 @@ ROOT@[0; 27) | |||
8 | L_PAREN@[6; 7) | 8 | L_PAREN@[6; 7) |
9 | R_PAREN@[7; 8) | 9 | R_PAREN@[7; 8) |
10 | WHITESPACE@[8; 9) | 10 | WHITESPACE@[8; 9) |
11 | THIN_ARROW@[9; 11) | 11 | RET_TYPE@[9; 23) |
12 | WHITESPACE@[11; 12) | 12 | THIN_ARROW@[9; 11) |
13 | PATH_TYPE@[12; 23) | 13 | WHITESPACE@[11; 12) |
14 | PATH@[12; 23) | 14 | PATH_TYPE@[12; 23) |
15 | PATH_SEGMENT@[12; 23) | 15 | PATH@[12; 23) |
16 | NAME_REF@[12; 15) | 16 | PATH_SEGMENT@[12; 23) |
17 | IDENT@[12; 15) "Box" | 17 | NAME_REF@[12; 15) |
18 | TYPE_ARG_LIST@[15; 23) | 18 | IDENT@[12; 15) "Box" |
19 | L_ANGLE@[15; 16) | 19 | TYPE_ARG_LIST@[15; 23) |
20 | TYPE_ARG@[16; 22) | 20 | L_ANGLE@[15; 16) |
21 | PATH_TYPE@[16; 22) | 21 | TYPE_ARG@[16; 22) |
22 | PATH@[16; 17) | 22 | PATH_TYPE@[16; 22) |
23 | PATH_SEGMENT@[16; 17) | 23 | PATH@[16; 17) |
24 | NAME_REF@[16; 17) | 24 | PATH_SEGMENT@[16; 17) |
25 | IDENT@[16; 17) "T" | 25 | NAME_REF@[16; 17) |
26 | WHITESPACE@[17; 18) | 26 | IDENT@[16; 17) "T" |
27 | PLUS@[18; 19) | 27 | WHITESPACE@[17; 18) |
28 | WHITESPACE@[19; 20) | 28 | PLUS@[18; 19) |
29 | LIFETIME@[20; 22) "'f" | 29 | WHITESPACE@[19; 20) |
30 | R_ANGLE@[22; 23) | 30 | LIFETIME@[20; 22) "'f" |
31 | R_ANGLE@[22; 23) | ||
31 | WHITESPACE@[23; 24) | 32 | WHITESPACE@[23; 24) |
32 | BLOCK@[24; 26) | 33 | BLOCK@[24; 26) |
33 | L_CURLY@[24; 25) | 34 | L_CURLY@[24; 25) |
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index 92ffb30c3..3ee0873f4 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs | |||
@@ -4,7 +4,7 @@ use languageserver_types::{ | |||
4 | Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, | 4 | Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, |
5 | Command, TextDocumentIdentifier, WorkspaceEdit, | 5 | Command, TextDocumentIdentifier, WorkspaceEdit, |
6 | SymbolInformation, Position, Location, TextEdit, | 6 | SymbolInformation, Position, Location, TextEdit, |
7 | CompletionItem, | 7 | CompletionItem, InsertTextFormat, CompletionItemKind, |
8 | }; | 8 | }; |
9 | use serde_json::{to_value, from_value}; | 9 | use serde_json::{to_value, from_value}; |
10 | use url_serde; | 10 | use url_serde; |
@@ -331,9 +331,17 @@ pub fn handle_completion( | |||
331 | Some(items) => items, | 331 | Some(items) => items, |
332 | }; | 332 | }; |
333 | let items = items.into_iter() | 333 | let items = items.into_iter() |
334 | .map(|item| CompletionItem { | 334 | .map(|item| { |
335 | label: item.name, | 335 | let mut res = CompletionItem { |
336 | .. Default::default() | 336 | label: item.name, |
337 | .. Default::default() | ||
338 | }; | ||
339 | if let Some(snip) = item.snippet { | ||
340 | res.insert_text = Some(snip); | ||
341 | res.insert_text_format = Some(InsertTextFormat::Snippet); | ||
342 | res.kind = Some(CompletionItemKind::Keyword); | ||
343 | }; | ||
344 | res | ||
337 | }) | 345 | }) |
338 | .collect(); | 346 | .collect(); |
339 | 347 | ||