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#[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#[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 #[serde(skip_serializing_if = "Option::is_none")]
68 pub snippet_support: Option<bool>,
69
70 #[serde(skip_serializing_if = "Option::is_none")]
72 pub commit_characters_support: Option<bool>,
73
74 #[serde(skip_serializing_if = "Option::is_none")]
77 pub documentation_format: Option<Vec<MarkupKind>>,
78
79 #[serde(skip_serializing_if = "Option::is_none")]
81 pub deprecated_support: Option<bool>,
82
83 #[serde(skip_serializing_if = "Option::is_none")]
85 pub preselect_support: Option<bool>,
86
87 #[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 #[serde(skip_serializing_if = "Option::is_none")]
103 pub insert_replace_support: Option<bool>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
111 pub resolve_support: Option<CompletionItemCapabilityResolveSupport>,
112
113 #[serde(skip_serializing_if = "Option::is_none")]
119 pub insert_text_mode_support: Option<InsertTextModeSupport>,
120
121 #[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 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#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
147#[serde(transparent)]
148pub struct InsertTextMode(i32);
149lsp_enum! {
150impl InsertTextMode {
151 pub const AS_IS: InsertTextMode = InsertTextMode(1);
157
158 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 #[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 #[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 #[serde(skip_serializing_if = "Option::is_none")]
213 pub dynamic_registration: Option<bool>,
214
215 #[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 #[serde(skip_serializing_if = "Option::is_none")]
226 pub context_support: Option<bool>,
227
228 #[serde(skip_serializing_if = "Option::is_none")]
233 pub insert_text_mode: Option<InsertTextMode>,
234
235 #[serde(skip_serializing_if = "Option::is_none")]
240 pub completion_list: Option<CompletionListCapability>,
241}
242
243#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
247#[serde(rename_all = "camelCase")]
248pub struct InsertReplaceEdit {
249 pub new_text: String,
251
252 pub insert: Range,
254
255 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#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
280#[serde(rename_all = "camelCase")]
281pub struct CompletionOptions {
282 #[serde(skip_serializing_if = "Option::is_none")]
284 pub resolve_provider: Option<bool>,
285
286 #[serde(skip_serializing_if = "Option::is_none")]
297 pub trigger_characters: Option<Vec<String>>,
298
299 #[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 #[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 #[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 #[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 #[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 pub trigger_kind: CompletionTriggerKind,
385
386 #[serde(skip_serializing_if = "Option::is_none")]
389 pub trigger_character: Option<String>,
390}
391
392#[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#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
407#[serde(rename_all = "camelCase")]
408pub struct CompletionList {
409 pub is_incomplete: bool,
412
413 pub items: Vec<CompletionItem>,
415}
416
417#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
418#[serde(rename_all = "camelCase")]
419pub struct CompletionItem {
420 pub label: String,
424
425 #[serde(skip_serializing_if = "Option::is_none")]
429 pub label_details: Option<CompletionItemLabelDetails>,
430
431 #[serde(skip_serializing_if = "Option::is_none")]
434 pub kind: Option<CompletionItemKind>,
435
436 #[serde(skip_serializing_if = "Option::is_none")]
439 pub detail: Option<String>,
440
441 #[serde(skip_serializing_if = "Option::is_none")]
443 pub documentation: Option<Documentation>,
444
445 #[serde(skip_serializing_if = "Option::is_none")]
447 pub deprecated: Option<bool>,
448
449 #[serde(skip_serializing_if = "Option::is_none")]
451 pub preselect: Option<bool>,
452
453 #[serde(skip_serializing_if = "Option::is_none")]
457 pub sort_text: Option<String>,
458
459 #[serde(skip_serializing_if = "Option::is_none")]
463 pub filter_text: Option<String>,
464
465 #[serde(skip_serializing_if = "Option::is_none")]
477 pub insert_text: Option<String>,
478
479 #[serde(skip_serializing_if = "Option::is_none")]
484 pub insert_text_format: Option<InsertTextFormat>,
485
486 #[serde(skip_serializing_if = "Option::is_none")]
493 pub insert_text_mode: Option<InsertTextMode>,
494
495 #[serde(skip_serializing_if = "Option::is_none")]
513 pub text_edit: Option<CompletionTextEdit>,
514
515 #[serde(skip_serializing_if = "Option::is_none")]
519 pub additional_text_edits: Option<Vec<TextEdit>>,
520
521 #[serde(skip_serializing_if = "Option::is_none")]
525 pub command: Option<Command>,
526
527 #[serde(skip_serializing_if = "Option::is_none")]
532 pub commit_characters: Option<Vec<String>>,
533
534 #[serde(skip_serializing_if = "Option::is_none")]
537 pub data: Option<Value>,
538
539 #[serde(skip_serializing_if = "Option::is_none")]
541 pub tags: Option<Vec<CompletionItemTag>>,
542}
543
544impl CompletionItem {
545 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#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
559#[serde(rename_all = "camelCase")]
560pub struct CompletionItemLabelDetails {
561 #[serde(skip_serializing_if = "Option::is_none")]
565 pub detail: Option<String>,
566
567 #[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}