1use serde::{Deserialize, Serialize};
2
3use crate::{
4 Command, Documentation, MarkupKind, OneOf, 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)]
405#[serde(rename_all = "camelCase")]
406pub struct CompletionListItemDefaultsEditRange {
407 pub insert: Range,
408 pub replace: Range,
409}
410
411#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
412#[serde(rename_all = "camelCase")]
413pub struct CompletionListItemDefaults {
414 #[serde(skip_serializing_if = "Option::is_none")]
415 pub commit_characters: Option<Vec<String>>,
416 #[serde(skip_serializing_if = "Option::is_none")]
417 pub edit_range: Option<OneOf<Range, CompletionListItemDefaultsEditRange>>,
418 #[serde(skip_serializing_if = "Option::is_none")]
419 pub insert_text_format: Option<InsertTextFormat>,
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub insert_text_mode: Option<InsertTextMode>,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 pub data: Option<serde_json::Value>,
424}
425
426#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
429#[serde(rename_all = "camelCase")]
430pub struct CompletionList {
431 pub is_incomplete: bool,
434
435 #[serde(skip_serializing_if = "Option::is_none")]
439 pub item_defaults: Option<CompletionListItemDefaults>,
440
441 pub items: Vec<CompletionItem>,
443}
444
445#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
446#[serde(rename_all = "camelCase")]
447pub struct CompletionItem {
448 pub label: String,
452
453 #[serde(skip_serializing_if = "Option::is_none")]
457 pub label_details: Option<CompletionItemLabelDetails>,
458
459 #[serde(skip_serializing_if = "Option::is_none")]
462 pub kind: Option<CompletionItemKind>,
463
464 #[serde(skip_serializing_if = "Option::is_none")]
467 pub detail: Option<String>,
468
469 #[serde(skip_serializing_if = "Option::is_none")]
471 pub documentation: Option<Documentation>,
472
473 #[serde(skip_serializing_if = "Option::is_none")]
475 pub deprecated: Option<bool>,
476
477 #[serde(skip_serializing_if = "Option::is_none")]
479 pub preselect: Option<bool>,
480
481 #[serde(skip_serializing_if = "Option::is_none")]
485 pub sort_text: Option<String>,
486
487 #[serde(skip_serializing_if = "Option::is_none")]
491 pub filter_text: Option<String>,
492
493 #[serde(skip_serializing_if = "Option::is_none")]
505 pub insert_text: Option<String>,
506
507 #[serde(skip_serializing_if = "Option::is_none")]
512 pub insert_text_format: Option<InsertTextFormat>,
513
514 #[serde(skip_serializing_if = "Option::is_none")]
521 pub insert_text_mode: Option<InsertTextMode>,
522
523 #[serde(skip_serializing_if = "Option::is_none")]
541 pub text_edit: Option<CompletionTextEdit>,
542
543 #[serde(skip_serializing_if = "Option::is_none")]
547 pub additional_text_edits: Option<Vec<TextEdit>>,
548
549 #[serde(skip_serializing_if = "Option::is_none")]
553 pub command: Option<Command>,
554
555 #[serde(skip_serializing_if = "Option::is_none")]
560 pub commit_characters: Option<Vec<String>>,
561
562 #[serde(skip_serializing_if = "Option::is_none")]
565 pub data: Option<Value>,
566
567 #[serde(skip_serializing_if = "Option::is_none")]
569 pub tags: Option<Vec<CompletionItemTag>>,
570}
571
572impl CompletionItem {
573 pub fn new_simple(label: String, detail: String) -> CompletionItem {
575 CompletionItem {
576 label,
577 detail: Some(detail),
578 ..Self::default()
579 }
580 }
581}
582
583#[derive(Debug, PartialEq, Default, Deserialize, Serialize, Clone)]
587#[serde(rename_all = "camelCase")]
588pub struct CompletionItemLabelDetails {
589 #[serde(skip_serializing_if = "Option::is_none")]
593 pub detail: Option<String>,
594
595 #[serde(skip_serializing_if = "Option::is_none")]
599 pub description: Option<String>,
600}
601
602#[cfg(test)]
603mod tests {
604 use super::*;
605 use crate::tests::test_deserialization;
606
607 #[test]
608 fn test_tag_support_deserialization() {
609 let mut empty = CompletionItemCapability::default();
610 empty.tag_support = None;
611
612 test_deserialization(r#"{}"#, &empty);
613 test_deserialization(r#"{"tagSupport": false}"#, &empty);
614
615 let mut t = CompletionItemCapability::default();
616 t.tag_support = Some(TagSupport { value_set: vec![] });
617 test_deserialization(r#"{"tagSupport": true}"#, &t);
618
619 let mut t = CompletionItemCapability::default();
620 t.tag_support = Some(TagSupport {
621 value_set: vec![CompletionItemTag::DEPRECATED],
622 });
623 test_deserialization(r#"{"tagSupport": {"valueSet": [1]}}"#, &t);
624 }
625
626 #[test]
627 fn test_debug_enum() {
628 assert_eq!(format!("{:?}", CompletionItemKind::TEXT), "Text");
629 assert_eq!(
630 format!("{:?}", CompletionItemKind::TYPE_PARAMETER),
631 "TypeParameter"
632 );
633 }
634
635 #[test]
636 fn test_try_from_enum() {
637 use std::convert::TryInto;
638 assert_eq!("Text".try_into(), Ok(CompletionItemKind::TEXT));
639 assert_eq!(
640 "TypeParameter".try_into(),
641 Ok(CompletionItemKind::TYPE_PARAMETER)
642 );
643 }
644}