1 use serde::{Deserialize, Serialize};
2 
3 use crate::{
4     Command, Documentation, MarkupKind, PartialResultParams, TagSupport,
5     TextDocumentPositionParams, TextDocumentRegistrationOptions, TextEdit, WorkDoneProgressOptions,
6     WorkDoneProgressParams,
7 };
8 
9 use crate::Range;
10 use serde_json::Value;
11 use std::fmt::Debug;
12 
13 /// Defines how to interpret the insert text in a completion item
14 #[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
15 #[serde(transparent)]
16 pub struct InsertTextFormat(i32);
17 lsp_enum! {
18 impl InsertTextFormat {
19     pub const PLAIN_TEXT: InsertTextFormat = InsertTextFormat(1);
20     pub const SNIPPET: InsertTextFormat = InsertTextFormat(2);
21 }
22 }
23 
24 /// The kind of a completion entry.
25 #[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
26 #[serde(transparent)]
27 pub struct CompletionItemKind(i32);
28 lsp_enum! {
29 impl CompletionItemKind {
30     pub const TEXT: CompletionItemKind = CompletionItemKind(1);
31     pub const METHOD: CompletionItemKind = CompletionItemKind(2);
32     pub const FUNCTION: CompletionItemKind = CompletionItemKind(3);
33     pub const CONSTRUCTOR: CompletionItemKind = CompletionItemKind(4);
34     pub const FIELD: CompletionItemKind = CompletionItemKind(5);
35     pub const VARIABLE: CompletionItemKind = CompletionItemKind(6);
36     pub const CLASS: CompletionItemKind = CompletionItemKind(7);
37     pub const INTERFACE: CompletionItemKind = CompletionItemKind(8);
38     pub const MODULE: CompletionItemKind = CompletionItemKind(9);
39     pub const PROPERTY: CompletionItemKind = CompletionItemKind(10);
40     pub const UNIT: CompletionItemKind = CompletionItemKind(11);
41     pub const VALUE: CompletionItemKind = CompletionItemKind(12);
42     pub const ENUM: CompletionItemKind = CompletionItemKind(13);
43     pub const KEYWORD: CompletionItemKind = CompletionItemKind(14);
44     pub const SNIPPET: CompletionItemKind = CompletionItemKind(15);
45     pub const COLOR: CompletionItemKind = CompletionItemKind(16);
46     pub const FILE: CompletionItemKind = CompletionItemKind(17);
47     pub const REFERENCE: CompletionItemKind = CompletionItemKind(18);
48     pub const FOLDER: CompletionItemKind = CompletionItemKind(19);
49     pub const ENUM_MEMBER: CompletionItemKind = CompletionItemKind(20);
50     pub const CONSTANT: CompletionItemKind = CompletionItemKind(21);
51     pub const STRUCT: CompletionItemKind = CompletionItemKind(22);
52     pub const EVENT: CompletionItemKind = CompletionItemKind(23);
53     pub const OPERATOR: CompletionItemKind = CompletionItemKind(24);
54     pub const TYPE_PARAMETER: CompletionItemKind = CompletionItemKind(25);
55 }
56 }
57 
58 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
59 #[serde(rename_all = "camelCase")]
60 pub struct CompletionItemCapability {
61     /// Client supports snippets as insert text.
62     ///
63     /// A snippet can define tab stops and placeholders with `$1`, `$2`
64     /// and `${3:foo}`. `$0` defines the final tab stop, it defaults to
65     /// the end of the snippet. Placeholders with equal identifiers are linked,
66     /// that is typing in one will update others too.
67     #[serde(skip_serializing_if = "Option::is_none")]
68     pub snippet_support: Option<bool>,
69 
70     /// Client supports commit characters on a completion item.
71     #[serde(skip_serializing_if = "Option::is_none")]
72     pub commit_characters_support: Option<bool>,
73 
74     /// Client supports the follow content formats for the documentation
75     /// property. The order describes the preferred format of the client.
76     #[serde(skip_serializing_if = "Option::is_none")]
77     pub documentation_format: Option<Vec<MarkupKind>>,
78 
79     /// Client supports the deprecated property on a completion item.
80     #[serde(skip_serializing_if = "Option::is_none")]
81     pub deprecated_support: Option<bool>,
82 
83     /// Client supports the preselect property on a completion item.
84     #[serde(skip_serializing_if = "Option::is_none")]
85     pub preselect_support: Option<bool>,
86 
87     /// Client supports the tag property on a completion item. Clients supporting
88     /// tags have to handle unknown tags gracefully. Clients especially need to
89     /// preserve unknown tags when sending a completion item back to the server in
90     /// a resolve call.
91     #[serde(
92         default,
93         skip_serializing_if = "Option::is_none",
94         deserialize_with = "TagSupport::deserialize_compat"
95     )]
96     pub tag_support: Option<TagSupport<CompletionItemTag>>,
97 
98     /// Client support insert replace edit to control different behavior if a
99     /// completion item is inserted in the text or should replace text.
100     ///
101     /// @since 3.16.0
102     #[serde(skip_serializing_if = "Option::is_none")]
103     pub insert_replace_support: Option<bool>,
104 
105     /// Indicates which properties a client can resolve lazily on a completion
106     /// item. Before version 3.16.0 only the predefined properties `documentation`
107     /// and `details` could be resolved lazily.
108     ///
109     /// @since 3.16.0
110     #[serde(skip_serializing_if = "Option::is_none")]
111     pub resolve_support: Option<CompletionItemCapabilityResolveSupport>,
112 
113     /// The client supports the `insertTextMode` property on
114     /// a completion item to override the whitespace handling mode
115     /// as defined by the client.
116     ///
117     /// @since 3.16.0
118     #[serde(skip_serializing_if = "Option::is_none")]
119     pub insert_text_mode_support: Option<InsertTextModeSupport>,
120 
121     /// The client has support for completion item label
122     /// details (see also `CompletionItemLabelDetails`).
123     ///
124     /// @since 3.17.0 - proposed state
125     ///
126     #[cfg(feature = "proposed")]
127     #[serde(skip_serializing_if = "Option::is_none")]
128     pub label_details_support: Option<bool>,
129 }
130 
131 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
132 #[serde(rename_all = "camelCase")]
133 pub struct CompletionItemCapabilityResolveSupport {
134     /// The properties that a client can resolve lazily.
135     pub properties: Vec<String>,
136 }
137 
138 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
139 #[serde(rename_all = "camelCase")]
140 pub struct InsertTextModeSupport {
141     pub value_set: Vec<InsertTextMode>,
142 }
143 
144 /// How whitespace and indentation is handled during completion
145 /// item insertion.
146 ///
147 /// @since 3.16.0
148 #[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
149 #[serde(transparent)]
150 pub struct InsertTextMode(i32);
151 lsp_enum! {
152 impl InsertTextMode {
153     /// The insertion or replace strings is taken as it is. If the
154     /// value is multi line the lines below the cursor will be
155     /// inserted using the indentation defined in the string value.
156     /// The client will not apply any kind of adjustments to the
157     /// string.
158     pub const AS_IS: InsertTextMode = InsertTextMode(1);
159 
160     /// The editor adjusts leading whitespace of new lines so that
161     /// they match the indentation up to the cursor of the line for
162     /// which the item is accepted.
163     ///
164     /// Consider a line like this: <2tabs><cursor><3tabs>foo. Accepting a
165     /// multi line completion item is indented using 2 tabs all
166     /// following lines inserted will be indented using 2 tabs as well.
167     pub const ADJUST_INDENTATION: InsertTextMode = InsertTextMode(2);
168 }
169 }
170 
171 #[derive(Eq, PartialEq, Clone, Deserialize, Serialize)]
172 #[serde(transparent)]
173 pub struct CompletionItemTag(i32);
174 lsp_enum! {
175 impl CompletionItemTag {
176     pub const DEPRECATED: CompletionItemTag = CompletionItemTag(1);
177 }
178 }
179 
180 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
181 #[serde(rename_all = "camelCase")]
182 pub struct CompletionItemKindCapability {
183     /// The completion item kind values the client supports. When this
184     /// property exists the client also guarantees that it will
185     /// handle values outside its set gracefully and falls back
186     /// to a default value when unknown.
187     ///
188     /// If this property is not present the client only supports
189     /// the completion items kinds from `Text` to `Reference` as defined in
190     /// the initial version of the protocol.
191     #[serde(skip_serializing_if = "Option::is_none")]
192     pub value_set: Option<Vec<CompletionItemKind>>,
193 }
194 
195 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
196 #[serde(rename_all = "camelCase")]
197 pub struct CompletionClientCapabilities {
198     /// Whether completion supports dynamic registration.
199     #[serde(skip_serializing_if = "Option::is_none")]
200     pub dynamic_registration: Option<bool>,
201 
202     /// The client supports the following `CompletionItem` specific
203     /// capabilities.
204     #[serde(skip_serializing_if = "Option::is_none")]
205     pub completion_item: Option<CompletionItemCapability>,
206 
207     #[serde(skip_serializing_if = "Option::is_none")]
208     pub completion_item_kind: Option<CompletionItemKindCapability>,
209 
210     /// The client supports to send additional context information for a
211     /// `textDocument/completion` requestion.
212     #[serde(skip_serializing_if = "Option::is_none")]
213     pub context_support: Option<bool>,
214 
215     /// The client's default when the completion item doesn't provide a
216     /// `insertTextMode` property.
217     ///
218     /// @since 3.17.0
219     #[cfg(feature = "proposed")]
220     #[serde(skip_serializing_if = "Option::is_none")]
221     pub insert_text_mode: Option<InsertTextMode>,
222 }
223 
224 /// A special text edit to provide an insert and a replace operation.
225 ///
226 /// @since 3.16.0
227 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
228 #[serde(rename_all = "camelCase")]
229 pub struct InsertReplaceEdit {
230     /// The string to be inserted.
231     pub new_text: String,
232 
233     /// The range if the insert is requested
234     pub insert: Range,
235 
236     /// The range if the replace is requested.
237     pub replace: Range,
238 }
239 
240 #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
241 #[serde(untagged)]
242 pub enum CompletionTextEdit {
243     Edit(TextEdit),
244     InsertAndReplace(InsertReplaceEdit),
245 }
246 
247 impl From<TextEdit> for CompletionTextEdit {
from(edit: TextEdit) -> Self248     fn from(edit: TextEdit) -> Self {
249         CompletionTextEdit::Edit(edit)
250     }
251 }
252 
253 impl From<InsertReplaceEdit> for CompletionTextEdit {
from(edit: InsertReplaceEdit) -> Self254     fn from(edit: InsertReplaceEdit) -> Self {
255         CompletionTextEdit::InsertAndReplace(edit)
256     }
257 }
258 
259 /// Completion options.
260 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
261 #[serde(rename_all = "camelCase")]
262 pub struct CompletionOptions {
263     /// The server provides support to resolve additional information for a completion item.
264     #[serde(skip_serializing_if = "Option::is_none")]
265     pub resolve_provider: Option<bool>,
266 
267     /// Most tools trigger completion request automatically without explicitly
268     /// requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they
269     /// do so when the user starts to type an identifier. For example if the user
270     /// types `c` in a JavaScript file code complete will automatically pop up
271     /// present `console` besides others as a completion item. Characters that
272     /// make up identifiers don't need to be listed here.
273     ///
274     /// If code complete should automatically be trigger on characters not being
275     /// valid inside an identifier (for example `.` in JavaScript) list them in
276     /// `triggerCharacters`.
277     #[serde(skip_serializing_if = "Option::is_none")]
278     pub trigger_characters: Option<Vec<String>>,
279 
280     /// The list of all possible characters that commit a completion. This field
281     /// can be used if clients don't support individual commit characters per
282     /// completion item. See client capability
283     /// `completion.completionItem.commitCharactersSupport`.
284     ///
285     /// If a server provides both `allCommitCharacters` and commit characters on
286     /// an individual completion item the ones on the completion item win.
287     ///
288     /// @since 3.2.0
289     #[serde(skip_serializing_if = "Option::is_none")]
290     pub all_commit_characters: Option<Vec<String>>,
291 
292     #[serde(flatten)]
293     pub work_done_progress_options: WorkDoneProgressOptions,
294 
295     /// The server supports the following `CompletionItem` specific
296     /// capabilities.
297     ///
298     /// @since 3.17.0 - proposed state
299     #[cfg(feature = "proposed")]
300     #[serde(skip_serializing_if = "Option::is_none")]
301     pub completion_item: Option<CompletionOptionsCompletionItem>,
302 }
303 
304 #[cfg(feature = "proposed")]
305 #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
306 #[serde(rename_all = "camelCase")]
307 pub struct CompletionOptionsCompletionItem {
308     /// The server has support for completion item label
309     /// details (see also `CompletionItemLabelDetails`) when receiving
310     /// a completion item in a resolve call.
311     ///
312     /// @since 3.17.0 - proposed state
313     #[serde(skip_serializing_if = "Option::is_none")]
314     pub label_details_support: Option<bool>,
315 }
316 
317 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
318 pub struct CompletionRegistrationOptions {
319     #[serde(flatten)]
320     pub text_document_registration_options: TextDocumentRegistrationOptions,
321 
322     #[serde(flatten)]
323     pub completion_options: CompletionOptions,
324 }
325 
326 #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
327 #[serde(untagged)]
328 pub enum CompletionResponse {
329     Array(Vec<CompletionItem>),
330     List(CompletionList),
331 }
332 
333 impl From<Vec<CompletionItem>> for CompletionResponse {
from(items: Vec<CompletionItem>) -> Self334     fn from(items: Vec<CompletionItem>) -> Self {
335         CompletionResponse::Array(items)
336     }
337 }
338 
339 impl From<CompletionList> for CompletionResponse {
from(list: CompletionList) -> Self340     fn from(list: CompletionList) -> Self {
341         CompletionResponse::List(list)
342     }
343 }
344 
345 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
346 #[serde(rename_all = "camelCase")]
347 pub struct CompletionParams {
348     // This field was "mixed-in" from TextDocumentPositionParams
349     #[serde(flatten)]
350     pub text_document_position: TextDocumentPositionParams,
351 
352     #[serde(flatten)]
353     pub work_done_progress_params: WorkDoneProgressParams,
354 
355     #[serde(flatten)]
356     pub partial_result_params: PartialResultParams,
357 
358     // CompletionParams properties:
359     #[serde(skip_serializing_if = "Option::is_none")]
360     pub context: Option<CompletionContext>,
361 }
362 
363 #[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
364 #[serde(rename_all = "camelCase")]
365 pub struct CompletionContext {
366     /// How the completion was triggered.
367     pub trigger_kind: CompletionTriggerKind,
368 
369     /// The trigger character (a single character) that has trigger code complete.
370     /// Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
371     #[serde(skip_serializing_if = "Option::is_none")]
372     pub trigger_character: Option<String>,
373 }
374 
375 /// How a completion was triggered.
376 #[derive(Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
377 #[serde(transparent)]
378 pub struct CompletionTriggerKind(i32);
379 lsp_enum! {
380 impl CompletionTriggerKind {
381     pub const INVOKED: CompletionTriggerKind = CompletionTriggerKind(1);
382     pub const TRIGGER_CHARACTER: CompletionTriggerKind = CompletionTriggerKind(2);
383     pub const TRIGGER_FOR_INCOMPLETE_COMPLETIONS: CompletionTriggerKind = CompletionTriggerKind(3);
384 }
385 }
386 
387 /// Represents a collection of [completion items](#CompletionItem) to be presented
388 /// in the editor.
389 #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
390 #[serde(rename_all = "camelCase")]
391 pub struct CompletionList {
392     /// This list it not complete. Further typing should result in recomputing
393     /// this list.
394     pub is_incomplete: bool,
395 
396     /// The completion items.
397     pub items: Vec<CompletionItem>,
398 }
399 
400 #[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
401 #[serde(rename_all = "camelCase")]
402 pub struct CompletionItem {
403     /// The label of this completion item. By default
404     /// also the text that is inserted when selecting
405     /// this completion.
406     pub label: String,
407 
408     /// Additional details for the label
409     ///
410     /// @since 3.17.0 - proposed state
411     ///
412     #[cfg(feature = "proposed")]
413     #[serde(skip_serializing_if = "Option::is_none")]
414     pub label_details: Option<CompletionItemLabelDetails>,
415 
416     /// The kind of this completion item. Based of the kind
417     /// an icon is chosen by the editor.
418     #[serde(skip_serializing_if = "Option::is_none")]
419     pub kind: Option<CompletionItemKind>,
420 
421     /// A human-readable string with additional information
422     /// about this item, like type or symbol information.
423     #[serde(skip_serializing_if = "Option::is_none")]
424     pub detail: Option<String>,
425 
426     /// A human-readable string that represents a doc-comment.
427     #[serde(skip_serializing_if = "Option::is_none")]
428     pub documentation: Option<Documentation>,
429 
430     /// Indicates if this item is deprecated.
431     #[serde(skip_serializing_if = "Option::is_none")]
432     pub deprecated: Option<bool>,
433 
434     /// Select this item when showing.
435     #[serde(skip_serializing_if = "Option::is_none")]
436     pub preselect: Option<bool>,
437 
438     /// A string that should be used when comparing this item
439     /// with other items. When `falsy` the label is used
440     /// as the sort text for this item.
441     #[serde(skip_serializing_if = "Option::is_none")]
442     pub sort_text: Option<String>,
443 
444     /// A string that should be used when filtering a set of
445     /// completion items. When `falsy` the label is used as the
446     /// filter text for this item.
447     #[serde(skip_serializing_if = "Option::is_none")]
448     pub filter_text: Option<String>,
449 
450     /// A string that should be inserted into a document when selecting
451     /// this completion. When `falsy` the label is used as the insert text
452     /// for this item.
453     ///
454     /// The `insertText` is subject to interpretation by the client side.
455     /// Some tools might not take the string literally. For example
456     /// VS Code when code complete is requested in this example
457     /// `con<cursor position>` and a completion item with an `insertText` of
458     /// `console` is provided it will only insert `sole`. Therefore it is
459     /// recommended to use `textEdit` instead since it avoids additional client
460     /// side interpretation.
461     #[serde(skip_serializing_if = "Option::is_none")]
462     pub insert_text: Option<String>,
463 
464     /// The format of the insert text. The format applies to both the `insertText` property
465     /// and the `newText` property of a provided `textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
466     ///
467     /// @since 3.16.0
468     #[serde(skip_serializing_if = "Option::is_none")]
469     pub insert_text_format: Option<InsertTextFormat>,
470 
471     /// How whitespace and indentation is handled during completion
472     /// item insertion. If not provided the client's default value is used.
473     ///
474     /// @since 3.16.0
475     #[serde(skip_serializing_if = "Option::is_none")]
476     pub insert_text_mode: Option<InsertTextMode>,
477 
478     /// An edit which is applied to a document when selecting
479     /// this completion. When an edit is provided the value of
480     /// insertText is ignored.
481     ///
482     /// Most editors support two different operation when accepting a completion item. One is to insert a
483 
484     /// completion text and the other is to replace an existing text with a completion text. Since this can
485     /// usually not predetermined by a server it can report both ranges. Clients need to signal support for
486     /// `InsertReplaceEdits` via the `textDocument.completion.insertReplaceSupport` client capability
487     /// property.
488     ///
489     /// *Note 1:* The text edit's range as well as both ranges from a insert replace edit must be a
490     /// [single line] and they must contain the position at which completion has been requested.
491     /// *Note 2:* If an `InsertReplaceEdit` is returned the edit's insert range must be a prefix of
492     /// the edit's replace range, that means it must be contained and starting at the same position.
493     ///
494     /// @since 3.16.0 additional type `InsertReplaceEdit`
495     #[serde(skip_serializing_if = "Option::is_none")]
496     pub text_edit: Option<CompletionTextEdit>,
497 
498     /// An optional array of additional text edits that are applied when
499     /// selecting this completion. Edits must not overlap with the main edit
500     /// nor with themselves.
501     #[serde(skip_serializing_if = "Option::is_none")]
502     pub additional_text_edits: Option<Vec<TextEdit>>,
503 
504     /// An optional command that is executed *after* inserting this completion. *Note* that
505     /// additional modifications to the current document should be described with the
506     /// additionalTextEdits-property.
507     #[serde(skip_serializing_if = "Option::is_none")]
508     pub command: Option<Command>,
509 
510     /// An optional set of characters that when pressed while this completion is
511     /// active will accept it first and then type that character. *Note* that all
512     /// commit characters should have `length=1` and that superfluous characters
513     /// will be ignored.
514     #[serde(skip_serializing_if = "Option::is_none")]
515     pub commit_characters: Option<Vec<String>>,
516 
517     /// An data entry field that is preserved on a completion item between
518     /// a completion and a completion resolve request.
519     #[serde(skip_serializing_if = "Option::is_none")]
520     pub data: Option<Value>,
521 
522     /// Tags for this completion item.
523     #[serde(skip_serializing_if = "Option::is_none")]
524     pub tags: Option<Vec<CompletionItemTag>>,
525 }
526 
527 impl CompletionItem {
528     /// Create a CompletionItem with the minimum possible info (label and detail).
new_simple(label: String, detail: String) -> CompletionItem529     pub fn new_simple(label: String, detail: String) -> CompletionItem {
530         CompletionItem {
531             label,
532             detail: Some(detail),
533             ..Self::default()
534         }
535     }
536 }
537 
538 /// Additional details for a completion item label.
539 ///
540 /// @since 3.17.0 - proposed state
541 #[cfg(feature = "proposed")]
542 #[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
543 #[serde(rename_all = "camelCase")]
544 pub struct CompletionItemLabelDetails {
545     /// An optional string which is rendered less prominently directly after
546     /// {@link CompletionItemLabel.label label}, without any spacing. Should be
547     /// used for function signatures or type annotations.
548     #[serde(skip_serializing_if = "Option::is_none")]
549     pub detail: Option<String>,
550 
551     /// An optional string which is rendered less prominently after
552     /// {@link CompletionItemLabel.detail}. Should be used for fully qualified
553     /// names or file path.
554     #[serde(skip_serializing_if = "Option::is_none")]
555     pub description: Option<String>,
556 }
557 
558 #[cfg(test)]
559 mod tests {
560     use super::*;
561     use crate::tests::test_deserialization;
562 
563     #[test]
test_tag_support_deserialization()564     fn test_tag_support_deserialization() {
565         let mut empty = CompletionItemCapability::default();
566         empty.tag_support = None;
567 
568         test_deserialization(r#"{}"#, &empty);
569         test_deserialization(r#"{"tagSupport": false}"#, &empty);
570 
571         let mut t = CompletionItemCapability::default();
572         t.tag_support = Some(TagSupport { value_set: vec![] });
573         test_deserialization(r#"{"tagSupport": true}"#, &t);
574 
575         let mut t = CompletionItemCapability::default();
576         t.tag_support = Some(TagSupport {
577             value_set: vec![CompletionItemTag::DEPRECATED],
578         });
579         test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t);
580     }
581 
582     #[test]
test_debug_enum()583     fn test_debug_enum() {
584         assert_eq!(format!("{:?}", CompletionItemKind::TEXT), "Text");
585         assert_eq!(
586             format!("{:?}", CompletionItemKind::TYPE_PARAMETER),
587             "TypeParameter"
588         );
589     }
590 }
591