@@ -44,65 +44,71 @@ pub fn completions_from_keywords() -> anyhow::Result<Option<Vec<CompletionItem>>
44
44
}
45
45
46
46
const BARE_KEYWORDS : & [ & str ] = & [
47
- "NULL" ,
48
- "NA" ,
49
47
"TRUE" ,
50
48
"FALSE" ,
49
+ "NULL" ,
51
50
"Inf" ,
52
51
"NaN" ,
52
+ "NA" ,
53
53
"NA_integer_" ,
54
54
"NA_real_" ,
55
- "NA_character_" ,
56
55
"NA_complex_" ,
56
+ "NA_character_" ,
57
+ "if" ,
58
+ "else" ,
59
+ "repeat" ,
60
+ "while" ,
61
+ "function" ,
62
+ "for" ,
57
63
"in" ,
58
64
"next" ,
59
65
"break" ,
60
- "repeat" ,
61
- "function" ,
62
66
] ;
63
67
64
- // Snippet data is a tuple of:
65
- // - keyword: The reserved word
66
- // - label: The label for the completion item, displayed on the left in the UI
67
- // - snippet: The snippet to be inserted
68
- // - label_detail.description: The description displayed on the right in the
69
- // completion UI
70
-
71
- // The only case where `keyword != label` is `fun` for `function`.
72
- // But in the name of preserving original behaviour, this is my opening
73
- // move.
74
- const KEYWORD_SNIPPETS : & [ ( & str , & str , & str , & str ) ] = & [
75
- // (keyword, label, snippet, label_detail.description)
76
- (
77
- "for" ,
78
- "for" ,
79
- "for (${1:variable} in ${2:vector}) {\n \t ${0}\n }" ,
80
- "Define a loop" ,
81
- ) ,
82
- (
83
- "if" ,
84
- "if" ,
85
- "if (${1:condition}) {\n \t ${0}\n }" ,
86
- "Conditional expression" ,
87
- ) ,
88
- (
89
- "while" ,
90
- "while" ,
91
- "while (${1:condition}) {\n \t ${0}\n }" ,
92
- "Define a loop" ,
93
- ) ,
94
- (
95
- "else" ,
96
- "else" ,
97
- "else {\n \t ${0}\n }" ,
98
- "Conditional expression" ,
99
- ) ,
100
- (
101
- "function" ,
102
- "fun" ,
103
- "${1:name} <- function(${2:variables}) {\n \t ${0}\n }" ,
104
- "Function skeleton" ,
105
- ) ,
68
+ struct KeywordSnippet {
69
+ keyword : & ' static str ,
70
+ label : & ' static str ,
71
+ snippet : & ' static str ,
72
+ label_details_description : & ' static str ,
73
+ }
74
+
75
+ const KEYWORD_SNIPPETS : & [ KeywordSnippet ] = & [
76
+ KeywordSnippet {
77
+ keyword : "if" ,
78
+ label : "if" ,
79
+ snippet : "if (${1:condition}) {\n \t ${0}\n }" ,
80
+ label_details_description : "An if statement" ,
81
+ } ,
82
+ KeywordSnippet {
83
+ keyword : "else" ,
84
+ label : "else" ,
85
+ snippet : "else {\n \t ${0}\n }" ,
86
+ label_details_description : "An else statement" ,
87
+ } ,
88
+ KeywordSnippet {
89
+ keyword : "repeat" ,
90
+ label : "repeat" ,
91
+ snippet : "repeat {\n \t ${0}\n }" ,
92
+ label_details_description : "A repeat loop" ,
93
+ } ,
94
+ KeywordSnippet {
95
+ keyword : "while" ,
96
+ label : "while" ,
97
+ snippet : "while (${1:condition}) {\n \t ${0}\n }" ,
98
+ label_details_description : "A while loop" ,
99
+ } ,
100
+ KeywordSnippet {
101
+ keyword : "function" ,
102
+ label : "fun" ,
103
+ snippet : "${1:name} <- function(${2:variables}) {\n \t ${0}\n }" ,
104
+ label_details_description : "Define a function" ,
105
+ } ,
106
+ KeywordSnippet {
107
+ keyword : "for" ,
108
+ label : "for" ,
109
+ snippet : "for (${1:variable} in ${2:vector}) {\n \t ${0}\n }" ,
110
+ label_details_description : "A for loop" ,
111
+ } ,
106
112
] ;
107
113
108
114
fn add_bare_keywords ( completions : & mut Vec < CompletionItem > ) {
@@ -127,7 +133,13 @@ fn add_bare_keywords(completions: &mut Vec<CompletionItem>) {
127
133
}
128
134
129
135
fn add_keyword_snippets ( completions : & mut Vec < CompletionItem > ) {
130
- for ( keyword, label, snippet, label_details_description) in KEYWORD_SNIPPETS {
136
+ for KeywordSnippet {
137
+ keyword,
138
+ label,
139
+ snippet,
140
+ label_details_description,
141
+ } in KEYWORD_SNIPPETS
142
+ {
131
143
let item = completion_item ( label. to_string ( ) , CompletionData :: Snippet {
132
144
text : snippet. to_string ( ) ,
133
145
} ) ;
@@ -168,9 +180,15 @@ mod tests {
168
180
#[ test]
169
181
fn test_presence_bare_keywords ( ) {
170
182
let completions = super :: completions_from_keywords ( ) . unwrap ( ) . unwrap ( ) ;
183
+ let keyword_completions: Vec < _ > = completions
184
+ . iter ( )
185
+ . filter ( |item| item. kind == Some ( tower_lsp:: lsp_types:: CompletionItemKind :: KEYWORD ) )
186
+ . collect ( ) ;
171
187
172
188
for keyword in super :: BARE_KEYWORDS {
173
- let item = completions. iter ( ) . find ( |item| item. label == * keyword) ;
189
+ let item = keyword_completions
190
+ . iter ( )
191
+ . find ( |item| item. label == * keyword) ;
174
192
assert ! (
175
193
item. is_some( ) ,
176
194
"Expected keyword '{keyword}' not found in completions"
@@ -183,32 +201,27 @@ mod tests {
183
201
description: Some ( "[keyword]" . to_string( ) ) ,
184
202
} )
185
203
) ;
186
- assert_eq ! (
187
- item. kind,
188
- Some ( tower_lsp:: lsp_types:: CompletionItemKind :: KEYWORD )
189
- ) ;
190
204
}
191
205
}
192
206
193
207
#[ test]
194
208
fn test_presence_keyword_snippets ( ) {
195
209
let completions = super :: completions_from_keywords ( ) . unwrap ( ) . unwrap ( ) ;
210
+ let snippet_completions: Vec < _ > = completions
211
+ . iter ( )
212
+ . filter ( |item| item. kind == Some ( tower_lsp:: lsp_types:: CompletionItemKind :: SNIPPET ) )
213
+ . collect ( ) ;
196
214
197
215
let snippet_labels: Vec < & str > = super :: KEYWORD_SNIPPETS
198
216
. iter ( )
199
- . map ( |( _ , label , _ , _ ) | * label)
217
+ . map ( |snippet| snippet . label )
200
218
. collect ( ) ;
201
219
202
220
for label in snippet_labels {
203
- let item = completions . iter ( ) . find ( |item| item. label == label) ;
221
+ let item = snippet_completions . iter ( ) . find ( |item| item. label == label) ;
204
222
assert ! (
205
223
item. is_some( ) ,
206
- "Expected snippet '{label}' not found in completions"
207
- ) ;
208
- let item = item. unwrap ( ) ;
209
- assert_eq ! (
210
- item. kind,
211
- Some ( tower_lsp:: lsp_types:: CompletionItemKind :: SNIPPET )
224
+ "Expected snippet '{label}' with SNIPPET kind not found in completions"
212
225
) ;
213
226
}
214
227
}
0 commit comments