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