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