1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
9pub struct Position {
10 pub line:u32,
12
13 pub character:u32,
15}
16
17impl Position {
18 pub fn new(line:u32, character:u32) -> Self { Self { line, character } }
20
21 pub fn zero() -> Self { Self { line:0, character:0 } }
23
24 pub fn from_line_column(line:u32, column:u32) -> Self {
26 Self { line:line.saturating_sub(1), character:column.saturating_sub(1) }
27 }
28}
29
30impl Default for Position {
31 fn default() -> Self { Self::zero() }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub struct Range {
37 pub start:Position,
39
40 pub end:Position,
42}
43
44impl Range {
45 pub fn new(start:Position, end:Position) -> Self { Self { start, end } }
47
48 pub fn empty(position:Position) -> Self { Self { start:position, end:position } }
50
51 pub fn contains(&self, position:Position) -> bool { position >= self.start && position <= self.end }
53}
54
55impl Default for Range {
56 fn default() -> Self { Self::empty(Position::zero()) }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
61pub struct Location {
62 pub uri:String,
64
65 pub range:Range,
67}
68
69impl Location {
70 pub fn new(uri:String, range:Range) -> Self { Self { uri, range } }
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Diagnostic {
77 pub range:Range,
79
80 pub severity:Option<DiagnosticSeverity>,
82
83 pub code:Option<DiagnosticCode>,
85
86 pub source:Option<String>,
88
89 pub message:String,
91
92 pub tags:Option<Vec<DiagnosticTag>>,
94
95 pub related_information:Option<Vec<DiagnosticRelatedInformation>>,
97}
98
99impl Diagnostic {
100 pub fn new(range:Range, message:String) -> Self {
102 Self {
103 range,
104
105 severity:None,
106
107 code:None,
108
109 source:None,
110
111 message,
112
113 tags:None,
114
115 related_information:None,
116 }
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
122pub enum DiagnosticSeverity {
123 Hint = 3,
125
126 Information = 2,
128
129 Warning = 1,
131
132 Error = 0,
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138#[serde(untagged)]
139pub enum DiagnosticCode {
140 Number(i64),
142
143 String(String),
145}
146
147#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
149pub enum DiagnosticTag {
150 Unnecessary = 1,
152
153 Deprecated = 2,
155}
156
157#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct DiagnosticRelatedInformation {
160 pub location:Location,
162
163 pub message:String,
165}
166
167#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct TextEdit {
170 pub range:Range,
172
173 pub new_text:String,
175}
176
177impl TextEdit {
178 pub fn new(range:Range, new_text:String) -> Self { Self { range, new_text } }
180
181 pub fn delete(range:Range) -> Self { Self { range, new_text:String::new() } }
183
184 pub fn insert(position:Position, new_text:String) -> Self { Self { range:Range::empty(position), new_text } }
186
187 pub fn replace(range:Range, new_text:String) -> Self { Self { range, new_text } }
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct WorkspaceEdit {
194 pub changes:Option<std::collections::HashMap<String, Vec<TextEdit>>>,
196}
197
198impl WorkspaceEdit {
199 pub fn new() -> Self { Self { changes:Some(std::collections::HashMap::new()) } }
201}
202
203impl Default for WorkspaceEdit {
204 fn default() -> Self { Self::new() }
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
209pub struct CompletionItem {
210 pub label:String,
212
213 pub kind:Option<CompletionItemKind>,
215
216 pub detail:Option<String>,
218
219 pub documentation:Option<CompletionItemDocumentation>,
221
222 #[serde(rename = "preselect")]
224 pub preselect:Option<bool>,
225
226 pub sort_text:Option<String>,
228
229 pub filter_text:Option<String>,
231}
232
233impl CompletionItem {
234 pub fn new(label:String) -> Self {
236 Self {
237 label,
238
239 kind:None,
240
241 detail:None,
242
243 documentation:None,
244
245 preselect:None,
246
247 sort_text:None,
248
249 filter_text:None,
250 }
251 }
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
256pub enum CompletionItemKind {
257 Text = 1,
259
260 Method = 2,
262
263 Function = 3,
265
266 Constructor = 4,
268
269 Field = 5,
271
272 Variable = 6,
274
275 Class = 7,
277
278 Interface = 8,
280
281 Module = 9,
283
284 Property = 10,
286
287 Unit = 11,
289
290 Value = 12,
292
293 Enum = 13,
295
296 Keyword = 14,
298
299 Snippet = 15,
301
302 Color = 16,
304
305 File = 17,
307
308 Reference = 18,
310
311 Folder = 19,
313
314 EnumMember = 20,
316
317 Constant = 21,
319
320 Struct = 22,
322
323 Event = 23,
325
326 Operator = 24,
328
329 TypeParameter = 25,
331}
332
333#[derive(Debug, Clone, Serialize, Deserialize)]
335#[serde(untagged)]
336pub enum CompletionItemDocumentation {
337 String(String),
339
340 Value(CompletionItemDocumentationValue),
342}
343
344#[derive(Debug, Clone, Serialize, Deserialize)]
346pub struct CompletionItemDocumentationValue {
347 pub kind:String,
349
350 pub value:String,
352}
353
354#[derive(Debug, Clone, Serialize, Deserialize)]
356pub struct PartialResultParams {
357 #[serde(rename = "partialResultToken")]
359 pub partial_result_token:Option<String>,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct WorkDoneProgressParams {
365 #[serde(rename = "workDoneToken")]
367 pub work_done_token:Option<String>,
368}
369
370#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
372pub struct TextDocumentIdentifier {
373 pub uri:String,
375}
376
377impl TextDocumentIdentifier {
378 pub fn new(uri:String) -> Self { Self { uri } }
380}
381
382#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
384pub struct VersionedTextDocumentIdentifier {
385 pub uri:String,
387
388 pub version:i32,
390}
391
392impl VersionedTextDocumentIdentifier {
393 pub fn new(uri:String, version:i32) -> Self { Self { uri, version } }
395}
396
397#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
399pub struct TextDocumentItem {
400 pub uri:String,
402
403 #[serde(rename = "languageId")]
405 pub language_id:String,
406
407 pub version:i32,
409
410 pub text:String,
412}
413
414impl TextDocumentItem {
415 pub fn new(uri:String, language_id:String, version:i32, text:String) -> Self {
417 Self { uri, language_id, version, text }
418 }
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize)]
424pub struct CreateFileParams {
425 pub files:Vec<FileCreate>,
427}
428
429#[derive(Debug, Clone, Serialize, Deserialize)]
431pub struct FileCreate {
432 pub uri:String,
434
435 #[serde(rename = "options")]
437 pub options:Option<CreateFileOptions>,
438}
439
440#[derive(Debug, Clone, Serialize, Deserialize)]
442pub struct CreateFileOptions {
443 #[serde(rename = "overwrite")]
445 pub overwrite:Option<bool>,
446
447 #[serde(rename = "ignoreIfExists")]
449 pub ignore_if_exists:Option<bool>,
450}
451
452#[cfg(test)]
453mod tests {
454
455 use super::*;
456
457 #[test]
458 fn test_position() {
459 let pos = Position::new(5, 10);
460
461 assert_eq!(pos.line, 5);
462
463 assert_eq!(pos.character, 10);
464
465 let default = Position::default();
466
467 assert_eq!(default.line, 0);
468
469 assert_eq!(default.character, 0);
470 }
471
472 #[test]
473 fn test_range() {
474 let start = Position::new(0, 0);
475
476 let end = Position::new(5, 10);
477
478 let range = Range::new(start, end);
479
480 assert!(range.contains(Position::new(3, 5)));
481
482 assert!(!range.contains(Position::new(6, 0)));
483 }
484
485 #[test]
486 fn test_text_edit_operations() {
487 let range = Range::new(Position::new(0, 0), Position::new(0, 5));
488
489 let replace = TextEdit::replace(range, "new text".to_string());
490
491 assert_eq!(replace.new_text, "new text");
492
493 let delete = TextEdit::delete(range);
494
495 assert_eq!(delete.new_text, "");
496
497 let insert = TextEdit::insert(Position::new(0, 0), "inserted".to_string());
498
499 assert_eq!(insert.new_text, "inserted");
500 }
501
502 #[test]
503 fn test_completion_item() {
504 let item = CompletionItem::new("testFunction".to_string());
505
506 assert_eq!(item.label, "testFunction");
507 }
508}