1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//! Types we need for communication with the server.

use ropey::Rope;
use serde::{Deserialize, Serialize};
use tower_lsp::lsp_types::{Position, Range};

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CopilotCyclingCompletion {
    pub display_text: String, // partial text
    pub text: String,         // fulltext
    pub range: Range,         // start char always 0
    pub position: Position,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Choices {
    pub text: String,
    pub index: i16,
    pub finish_reason: Option<String>,
    pub logprobs: Option<String>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CopilotCompletionResponse {
    pub completions: Vec<CopilotCyclingCompletion>,
    pub cancellation_reason: Option<String>,
}

impl CopilotCompletionResponse {
    pub fn from_str_vec(str_vec: Vec<String>, line_before: String, pos: Position) -> Self {
        let completions = str_vec
            .iter()
            .map(|x| CopilotCyclingCompletion::new(x.to_string(), line_before.to_string(), pos))
            .collect();
        Self {
            completions,
            cancellation_reason: None,
        }
    }
}

impl CopilotCyclingCompletion {
    pub fn new(text: String, line_before: String, position: Position) -> Self {
        let display_text = text.clone();
        let text = format!("{}{}", line_before, text);
        let end_char = text.find('\n').unwrap_or(text.len()) as u32;
        Self {
            display_text, // partial text
            text,         // fulltext
            range: Range {
                start: Position {
                    character: 0,
                    line: position.line,
                },
                end: Position {
                    character: end_char,
                    line: position.line,
                },
            }, // start char always 0
            position,
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
struct LanguageEntry {
    language_id: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
struct EditorConfiguration {
    disabled_languages: Vec<LanguageEntry>,
    enable_auto_completions: bool,
}

impl Default for EditorConfiguration {
    fn default() -> Self {
        Self {
            disabled_languages: vec![],
            enable_auto_completions: true,
        }
    }
}
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
struct EditorInfo {
    name: String,
    version: String,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CopilotEditorInfo {
    editor_configuration: EditorConfiguration,
    editor_info: EditorInfo,
    editor_plugin_info: EditorInfo,
}

pub struct DocParams {
    pub rope: Rope,
    pub uri: String,
    pub pos: Position,
    pub language: String,
    pub line_before: String,
    pub prefix: String,
    pub suffix: String,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CopilotLspCompletionParams {
    pub doc: CopilotDocParams,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct CopilotDocParams {
    pub indent_size: u32,
    pub insert_spaces: bool,
    pub language_id: String,
    pub path: String,
    pub position: Position,
    pub relative_path: String,
    pub source: String,
    pub tab_size: u32,
    pub uri: String,
}