1use std::collections::BTreeMap;
8
9use schemars::{JsonSchema, Schema};
10use serde::{Deserialize, Serialize};
11use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
12
13use super::{Meta, SessionId};
14use crate::{IntoOption, SkipListener};
15
16pub(crate) const NES_START_METHOD_NAME: &str = "nes/start";
20pub(crate) const NES_SUGGEST_METHOD_NAME: &str = "nes/suggest";
22pub(crate) const NES_ACCEPT_METHOD_NAME: &str = "nes/accept";
24pub(crate) const NES_REJECT_METHOD_NAME: &str = "nes/reject";
26pub(crate) const NES_CLOSE_METHOD_NAME: &str = "nes/close";
28pub(crate) const DOCUMENT_DID_OPEN_METHOD_NAME: &str = "document/didOpen";
30pub(crate) const DOCUMENT_DID_CHANGE_METHOD_NAME: &str = "document/didChange";
32pub(crate) const DOCUMENT_DID_CLOSE_METHOD_NAME: &str = "document/didClose";
34pub(crate) const DOCUMENT_DID_SAVE_METHOD_NAME: &str = "document/didSave";
36pub(crate) const DOCUMENT_DID_FOCUS_METHOD_NAME: &str = "document/didFocus";
38
39#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
45#[non_exhaustive]
46pub enum PositionEncodingKind {
47 #[serde(rename = "utf-16")]
49 Utf16,
50 #[serde(rename = "utf-32")]
52 Utf32,
53 #[serde(rename = "utf-8")]
55 Utf8,
56}
57
58#[skip_serializing_none]
62#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
63#[serde(rename_all = "camelCase")]
64#[non_exhaustive]
65pub struct Position {
66 pub line: u32,
68 pub character: u32,
70 #[serde(rename = "_meta")]
76 pub meta: Option<Meta>,
77}
78
79impl Position {
80 #[must_use]
82 pub fn new(line: u32, character: u32) -> Self {
83 Self {
84 line,
85 character,
86 meta: None,
87 }
88 }
89
90 #[must_use]
96 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
97 self.meta = meta.into_option();
98 self
99 }
100}
101
102#[skip_serializing_none]
104#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
105#[serde(rename_all = "camelCase")]
106#[non_exhaustive]
107pub struct Range {
108 pub start: Position,
110 pub end: Position,
112 #[serde(rename = "_meta")]
118 pub meta: Option<Meta>,
119}
120
121impl Range {
122 #[must_use]
124 pub fn new(start: Position, end: Position) -> Self {
125 Self {
126 start,
127 end,
128 meta: None,
129 }
130 }
131
132 #[must_use]
138 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
139 self.meta = meta.into_option();
140 self
141 }
142}
143
144#[serde_as]
151#[skip_serializing_none]
152#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
153#[serde(rename_all = "camelCase")]
154#[non_exhaustive]
155pub struct NesCapabilities {
156 #[serde_as(deserialize_as = "DefaultOnError")]
158 #[schemars(extend("x-deserialize-default-on-error" = true))]
159 #[serde(default)]
160 pub events: Option<NesEventCapabilities>,
161 #[serde_as(deserialize_as = "DefaultOnError")]
163 #[schemars(extend("x-deserialize-default-on-error" = true))]
164 #[serde(default)]
165 pub context: Option<NesContextCapabilities>,
166 #[serde(rename = "_meta")]
172 pub meta: Option<Meta>,
173}
174
175impl NesCapabilities {
176 #[must_use]
178 pub fn new() -> Self {
179 Self::default()
180 }
181
182 #[must_use]
184 pub fn events(mut self, events: impl IntoOption<NesEventCapabilities>) -> Self {
185 self.events = events.into_option();
186 self
187 }
188
189 #[must_use]
191 pub fn context(mut self, context: impl IntoOption<NesContextCapabilities>) -> Self {
192 self.context = context.into_option();
193 self
194 }
195
196 #[must_use]
202 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
203 self.meta = meta.into_option();
204 self
205 }
206}
207
208#[serde_as]
210#[skip_serializing_none]
211#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
212#[serde(rename_all = "camelCase")]
213#[non_exhaustive]
214pub struct NesEventCapabilities {
215 #[serde_as(deserialize_as = "DefaultOnError")]
217 #[schemars(extend("x-deserialize-default-on-error" = true))]
218 #[serde(default)]
219 pub document: Option<NesDocumentEventCapabilities>,
220 #[serde(rename = "_meta")]
226 pub meta: Option<Meta>,
227}
228
229impl NesEventCapabilities {
230 #[must_use]
232 pub fn new() -> Self {
233 Self::default()
234 }
235
236 #[must_use]
238 pub fn document(mut self, document: impl IntoOption<NesDocumentEventCapabilities>) -> Self {
239 self.document = document.into_option();
240 self
241 }
242
243 #[must_use]
249 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
250 self.meta = meta.into_option();
251 self
252 }
253}
254
255#[serde_as]
257#[skip_serializing_none]
258#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
259#[serde(rename_all = "camelCase")]
260#[non_exhaustive]
261pub struct NesDocumentEventCapabilities {
262 #[serde_as(deserialize_as = "DefaultOnError")]
264 #[schemars(extend("x-deserialize-default-on-error" = true))]
265 #[serde(default)]
266 pub did_open: Option<NesDocumentDidOpenCapabilities>,
267 #[serde_as(deserialize_as = "DefaultOnError")]
269 #[schemars(extend("x-deserialize-default-on-error" = true))]
270 #[serde(default)]
271 pub did_change: Option<NesDocumentDidChangeCapabilities>,
272 #[serde_as(deserialize_as = "DefaultOnError")]
274 #[schemars(extend("x-deserialize-default-on-error" = true))]
275 #[serde(default)]
276 pub did_close: Option<NesDocumentDidCloseCapabilities>,
277 #[serde_as(deserialize_as = "DefaultOnError")]
279 #[schemars(extend("x-deserialize-default-on-error" = true))]
280 #[serde(default)]
281 pub did_save: Option<NesDocumentDidSaveCapabilities>,
282 #[serde_as(deserialize_as = "DefaultOnError")]
284 #[schemars(extend("x-deserialize-default-on-error" = true))]
285 #[serde(default)]
286 pub did_focus: Option<NesDocumentDidFocusCapabilities>,
287 #[serde(rename = "_meta")]
293 pub meta: Option<Meta>,
294}
295
296impl NesDocumentEventCapabilities {
297 #[must_use]
299 pub fn new() -> Self {
300 Self::default()
301 }
302
303 #[must_use]
305 pub fn did_open(mut self, did_open: impl IntoOption<NesDocumentDidOpenCapabilities>) -> Self {
306 self.did_open = did_open.into_option();
307 self
308 }
309
310 #[must_use]
312 pub fn did_change(
313 mut self,
314 did_change: impl IntoOption<NesDocumentDidChangeCapabilities>,
315 ) -> Self {
316 self.did_change = did_change.into_option();
317 self
318 }
319
320 #[must_use]
322 pub fn did_close(
323 mut self,
324 did_close: impl IntoOption<NesDocumentDidCloseCapabilities>,
325 ) -> Self {
326 self.did_close = did_close.into_option();
327 self
328 }
329
330 #[must_use]
332 pub fn did_save(mut self, did_save: impl IntoOption<NesDocumentDidSaveCapabilities>) -> Self {
333 self.did_save = did_save.into_option();
334 self
335 }
336
337 #[must_use]
339 pub fn did_focus(
340 mut self,
341 did_focus: impl IntoOption<NesDocumentDidFocusCapabilities>,
342 ) -> Self {
343 self.did_focus = did_focus.into_option();
344 self
345 }
346
347 #[must_use]
353 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
354 self.meta = meta.into_option();
355 self
356 }
357}
358
359#[skip_serializing_none]
361#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
362#[serde(rename_all = "camelCase")]
363#[non_exhaustive]
364pub struct NesDocumentDidOpenCapabilities {
365 #[serde(rename = "_meta")]
371 pub meta: Option<Meta>,
372}
373
374impl NesDocumentDidOpenCapabilities {
375 #[must_use]
377 pub fn new() -> Self {
378 Self::default()
379 }
380}
381
382#[skip_serializing_none]
384#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
385#[serde(rename_all = "camelCase")]
386#[non_exhaustive]
387pub struct NesDocumentDidChangeCapabilities {
388 pub sync_kind: TextDocumentSyncKind,
390 #[serde(rename = "_meta")]
396 pub meta: Option<Meta>,
397}
398
399impl NesDocumentDidChangeCapabilities {
400 #[must_use]
402 pub fn new(sync_kind: TextDocumentSyncKind) -> Self {
403 Self {
404 sync_kind,
405 meta: None,
406 }
407 }
408
409 #[must_use]
415 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
416 self.meta = meta.into_option();
417 self
418 }
419}
420
421#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
423#[non_exhaustive]
424pub enum TextDocumentSyncKind {
425 #[serde(rename = "full")]
427 Full,
428 #[serde(rename = "incremental")]
430 Incremental,
431}
432
433#[skip_serializing_none]
435#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
436#[serde(rename_all = "camelCase")]
437#[non_exhaustive]
438pub struct NesDocumentDidCloseCapabilities {
439 #[serde(rename = "_meta")]
445 pub meta: Option<Meta>,
446}
447
448impl NesDocumentDidCloseCapabilities {
449 #[must_use]
451 pub fn new() -> Self {
452 Self::default()
453 }
454}
455
456#[skip_serializing_none]
458#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
459#[serde(rename_all = "camelCase")]
460#[non_exhaustive]
461pub struct NesDocumentDidSaveCapabilities {
462 #[serde(rename = "_meta")]
468 pub meta: Option<Meta>,
469}
470
471impl NesDocumentDidSaveCapabilities {
472 #[must_use]
474 pub fn new() -> Self {
475 Self::default()
476 }
477}
478
479#[skip_serializing_none]
481#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
482#[serde(rename_all = "camelCase")]
483#[non_exhaustive]
484pub struct NesDocumentDidFocusCapabilities {
485 #[serde(rename = "_meta")]
491 pub meta: Option<Meta>,
492}
493
494impl NesDocumentDidFocusCapabilities {
495 #[must_use]
497 pub fn new() -> Self {
498 Self::default()
499 }
500}
501
502#[serde_as]
504#[skip_serializing_none]
505#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
506#[serde(rename_all = "camelCase")]
507#[non_exhaustive]
508pub struct NesContextCapabilities {
509 #[serde_as(deserialize_as = "DefaultOnError")]
511 #[schemars(extend("x-deserialize-default-on-error" = true))]
512 #[serde(default)]
513 pub recent_files: Option<NesRecentFilesCapabilities>,
514 #[serde_as(deserialize_as = "DefaultOnError")]
516 #[schemars(extend("x-deserialize-default-on-error" = true))]
517 #[serde(default)]
518 pub related_snippets: Option<NesRelatedSnippetsCapabilities>,
519 #[serde_as(deserialize_as = "DefaultOnError")]
521 #[schemars(extend("x-deserialize-default-on-error" = true))]
522 #[serde(default)]
523 pub edit_history: Option<NesEditHistoryCapabilities>,
524 #[serde_as(deserialize_as = "DefaultOnError")]
526 #[schemars(extend("x-deserialize-default-on-error" = true))]
527 #[serde(default)]
528 pub user_actions: Option<NesUserActionsCapabilities>,
529 #[serde_as(deserialize_as = "DefaultOnError")]
531 #[schemars(extend("x-deserialize-default-on-error" = true))]
532 #[serde(default)]
533 pub open_files: Option<NesOpenFilesCapabilities>,
534 #[serde_as(deserialize_as = "DefaultOnError")]
536 #[schemars(extend("x-deserialize-default-on-error" = true))]
537 #[serde(default)]
538 pub diagnostics: Option<NesDiagnosticsCapabilities>,
539 #[serde(rename = "_meta")]
545 pub meta: Option<Meta>,
546}
547
548impl NesContextCapabilities {
549 #[must_use]
551 pub fn new() -> Self {
552 Self::default()
553 }
554
555 #[must_use]
557 pub fn recent_files(
558 mut self,
559 recent_files: impl IntoOption<NesRecentFilesCapabilities>,
560 ) -> Self {
561 self.recent_files = recent_files.into_option();
562 self
563 }
564
565 #[must_use]
567 pub fn related_snippets(
568 mut self,
569 related_snippets: impl IntoOption<NesRelatedSnippetsCapabilities>,
570 ) -> Self {
571 self.related_snippets = related_snippets.into_option();
572 self
573 }
574
575 #[must_use]
577 pub fn edit_history(
578 mut self,
579 edit_history: impl IntoOption<NesEditHistoryCapabilities>,
580 ) -> Self {
581 self.edit_history = edit_history.into_option();
582 self
583 }
584
585 #[must_use]
587 pub fn user_actions(
588 mut self,
589 user_actions: impl IntoOption<NesUserActionsCapabilities>,
590 ) -> Self {
591 self.user_actions = user_actions.into_option();
592 self
593 }
594
595 #[must_use]
597 pub fn open_files(mut self, open_files: impl IntoOption<NesOpenFilesCapabilities>) -> Self {
598 self.open_files = open_files.into_option();
599 self
600 }
601
602 #[must_use]
604 pub fn diagnostics(mut self, diagnostics: impl IntoOption<NesDiagnosticsCapabilities>) -> Self {
605 self.diagnostics = diagnostics.into_option();
606 self
607 }
608
609 #[must_use]
615 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
616 self.meta = meta.into_option();
617 self
618 }
619}
620
621#[skip_serializing_none]
623#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
624#[serde(rename_all = "camelCase")]
625#[non_exhaustive]
626pub struct NesRecentFilesCapabilities {
627 pub max_count: Option<u32>,
629 #[serde(rename = "_meta")]
635 pub meta: Option<Meta>,
636}
637
638impl NesRecentFilesCapabilities {
639 #[must_use]
641 pub fn new() -> Self {
642 Self::default()
643 }
644}
645
646#[skip_serializing_none]
648#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
649#[serde(rename_all = "camelCase")]
650#[non_exhaustive]
651pub struct NesRelatedSnippetsCapabilities {
652 #[serde(rename = "_meta")]
658 pub meta: Option<Meta>,
659}
660
661impl NesRelatedSnippetsCapabilities {
662 #[must_use]
664 pub fn new() -> Self {
665 Self::default()
666 }
667}
668
669#[skip_serializing_none]
671#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
672#[serde(rename_all = "camelCase")]
673#[non_exhaustive]
674pub struct NesEditHistoryCapabilities {
675 pub max_count: Option<u32>,
677 #[serde(rename = "_meta")]
683 pub meta: Option<Meta>,
684}
685
686impl NesEditHistoryCapabilities {
687 #[must_use]
689 pub fn new() -> Self {
690 Self::default()
691 }
692}
693
694#[skip_serializing_none]
696#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
697#[serde(rename_all = "camelCase")]
698#[non_exhaustive]
699pub struct NesUserActionsCapabilities {
700 pub max_count: Option<u32>,
702 #[serde(rename = "_meta")]
708 pub meta: Option<Meta>,
709}
710
711impl NesUserActionsCapabilities {
712 #[must_use]
714 pub fn new() -> Self {
715 Self::default()
716 }
717}
718
719#[skip_serializing_none]
721#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
722#[serde(rename_all = "camelCase")]
723#[non_exhaustive]
724pub struct NesOpenFilesCapabilities {
725 #[serde(rename = "_meta")]
731 pub meta: Option<Meta>,
732}
733
734impl NesOpenFilesCapabilities {
735 #[must_use]
737 pub fn new() -> Self {
738 Self::default()
739 }
740}
741
742#[skip_serializing_none]
744#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
745#[serde(rename_all = "camelCase")]
746#[non_exhaustive]
747pub struct NesDiagnosticsCapabilities {
748 #[serde(rename = "_meta")]
754 pub meta: Option<Meta>,
755}
756
757impl NesDiagnosticsCapabilities {
758 #[must_use]
760 pub fn new() -> Self {
761 Self::default()
762 }
763}
764
765#[serde_as]
769#[skip_serializing_none]
770#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
771#[serde(rename_all = "camelCase")]
772#[non_exhaustive]
773pub struct ClientNesCapabilities {
774 #[serde_as(deserialize_as = "DefaultOnError")]
776 #[schemars(extend("x-deserialize-default-on-error" = true))]
777 #[serde(default)]
778 pub jump: Option<NesJumpCapabilities>,
779 #[serde_as(deserialize_as = "DefaultOnError")]
781 #[schemars(extend("x-deserialize-default-on-error" = true))]
782 #[serde(default)]
783 pub rename: Option<NesRenameCapabilities>,
784 #[serde_as(deserialize_as = "DefaultOnError")]
786 #[schemars(extend("x-deserialize-default-on-error" = true))]
787 #[serde(default)]
788 pub search_and_replace: Option<NesSearchAndReplaceCapabilities>,
789 #[serde(rename = "_meta")]
795 pub meta: Option<Meta>,
796}
797
798impl ClientNesCapabilities {
799 #[must_use]
801 pub fn new() -> Self {
802 Self::default()
803 }
804
805 #[must_use]
807 pub fn jump(mut self, jump: impl IntoOption<NesJumpCapabilities>) -> Self {
808 self.jump = jump.into_option();
809 self
810 }
811
812 #[must_use]
814 pub fn rename(mut self, rename: impl IntoOption<NesRenameCapabilities>) -> Self {
815 self.rename = rename.into_option();
816 self
817 }
818
819 #[must_use]
821 pub fn search_and_replace(
822 mut self,
823 search_and_replace: impl IntoOption<NesSearchAndReplaceCapabilities>,
824 ) -> Self {
825 self.search_and_replace = search_and_replace.into_option();
826 self
827 }
828
829 #[must_use]
835 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
836 self.meta = meta.into_option();
837 self
838 }
839}
840
841#[skip_serializing_none]
843#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
844#[serde(rename_all = "camelCase")]
845#[non_exhaustive]
846pub struct NesJumpCapabilities {
847 #[serde(rename = "_meta")]
853 pub meta: Option<Meta>,
854}
855
856impl NesJumpCapabilities {
857 #[must_use]
859 pub fn new() -> Self {
860 Self::default()
861 }
862}
863
864#[skip_serializing_none]
866#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
867#[serde(rename_all = "camelCase")]
868#[non_exhaustive]
869pub struct NesRenameCapabilities {
870 #[serde(rename = "_meta")]
876 pub meta: Option<Meta>,
877}
878
879impl NesRenameCapabilities {
880 #[must_use]
882 pub fn new() -> Self {
883 Self::default()
884 }
885}
886
887#[skip_serializing_none]
889#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
890#[serde(rename_all = "camelCase")]
891#[non_exhaustive]
892pub struct NesSearchAndReplaceCapabilities {
893 #[serde(rename = "_meta")]
899 pub meta: Option<Meta>,
900}
901
902impl NesSearchAndReplaceCapabilities {
903 #[must_use]
905 pub fn new() -> Self {
906 Self::default()
907 }
908}
909
910#[skip_serializing_none]
914#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
915#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_OPEN_METHOD_NAME))]
916#[serde(rename_all = "camelCase")]
917#[non_exhaustive]
918pub struct DidOpenDocumentNotification {
919 pub session_id: SessionId,
921 pub uri: String,
923 pub language_id: String,
925 pub version: i64,
927 pub text: String,
929 #[serde(rename = "_meta")]
935 pub meta: Option<Meta>,
936}
937
938impl DidOpenDocumentNotification {
939 #[must_use]
941 pub fn new(
942 session_id: impl Into<SessionId>,
943 uri: impl Into<String>,
944 language_id: impl Into<String>,
945 version: i64,
946 text: impl Into<String>,
947 ) -> Self {
948 Self {
949 session_id: session_id.into(),
950 uri: uri.into(),
951 language_id: language_id.into(),
952 version,
953 text: text.into(),
954 meta: None,
955 }
956 }
957
958 #[must_use]
964 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
965 self.meta = meta.into_option();
966 self
967 }
968}
969
970#[skip_serializing_none]
972#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
973#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CHANGE_METHOD_NAME))]
974#[serde(rename_all = "camelCase")]
975#[non_exhaustive]
976pub struct DidChangeDocumentNotification {
977 pub session_id: SessionId,
979 pub uri: String,
981 pub version: i64,
983 pub content_changes: Vec<TextDocumentContentChangeEvent>,
985 #[serde(rename = "_meta")]
991 pub meta: Option<Meta>,
992}
993
994impl DidChangeDocumentNotification {
995 #[must_use]
997 pub fn new(
998 session_id: impl Into<SessionId>,
999 uri: impl Into<String>,
1000 version: i64,
1001 content_changes: Vec<TextDocumentContentChangeEvent>,
1002 ) -> Self {
1003 Self {
1004 session_id: session_id.into(),
1005 uri: uri.into(),
1006 version,
1007 content_changes,
1008 meta: None,
1009 }
1010 }
1011
1012 #[must_use]
1018 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1019 self.meta = meta.into_option();
1020 self
1021 }
1022}
1023
1024#[skip_serializing_none]
1029#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1030#[serde(rename_all = "camelCase")]
1031#[non_exhaustive]
1032pub struct TextDocumentContentChangeEvent {
1033 pub range: Option<Range>,
1035 pub text: String,
1037 #[serde(rename = "_meta")]
1043 pub meta: Option<Meta>,
1044}
1045
1046impl TextDocumentContentChangeEvent {
1047 #[must_use]
1049 pub fn full(text: impl Into<String>) -> Self {
1050 Self {
1051 range: None,
1052 text: text.into(),
1053 meta: None,
1054 }
1055 }
1056
1057 #[must_use]
1059 pub fn incremental(range: Range, text: impl Into<String>) -> Self {
1060 Self {
1061 range: Some(range),
1062 text: text.into(),
1063 meta: None,
1064 }
1065 }
1066
1067 #[must_use]
1073 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1074 self.meta = meta.into_option();
1075 self
1076 }
1077}
1078
1079#[skip_serializing_none]
1081#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1082#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CLOSE_METHOD_NAME))]
1083#[serde(rename_all = "camelCase")]
1084#[non_exhaustive]
1085pub struct DidCloseDocumentNotification {
1086 pub session_id: SessionId,
1088 pub uri: String,
1090 #[serde(rename = "_meta")]
1096 pub meta: Option<Meta>,
1097}
1098
1099impl DidCloseDocumentNotification {
1100 #[must_use]
1102 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1103 Self {
1104 session_id: session_id.into(),
1105 uri: uri.into(),
1106 meta: None,
1107 }
1108 }
1109
1110 #[must_use]
1116 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1117 self.meta = meta.into_option();
1118 self
1119 }
1120}
1121
1122#[skip_serializing_none]
1124#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1125#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_SAVE_METHOD_NAME))]
1126#[serde(rename_all = "camelCase")]
1127#[non_exhaustive]
1128pub struct DidSaveDocumentNotification {
1129 pub session_id: SessionId,
1131 pub uri: String,
1133 #[serde(rename = "_meta")]
1139 pub meta: Option<Meta>,
1140}
1141
1142impl DidSaveDocumentNotification {
1143 #[must_use]
1145 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1146 Self {
1147 session_id: session_id.into(),
1148 uri: uri.into(),
1149 meta: None,
1150 }
1151 }
1152
1153 #[must_use]
1159 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1160 self.meta = meta.into_option();
1161 self
1162 }
1163}
1164
1165#[skip_serializing_none]
1167#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1168#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_FOCUS_METHOD_NAME))]
1169#[serde(rename_all = "camelCase")]
1170#[non_exhaustive]
1171pub struct DidFocusDocumentNotification {
1172 pub session_id: SessionId,
1174 pub uri: String,
1176 pub version: i64,
1178 pub position: Position,
1180 pub visible_range: Range,
1182 #[serde(rename = "_meta")]
1188 pub meta: Option<Meta>,
1189}
1190
1191impl DidFocusDocumentNotification {
1192 #[must_use]
1194 pub fn new(
1195 session_id: impl Into<SessionId>,
1196 uri: impl Into<String>,
1197 version: i64,
1198 position: Position,
1199 visible_range: Range,
1200 ) -> Self {
1201 Self {
1202 session_id: session_id.into(),
1203 uri: uri.into(),
1204 version,
1205 position,
1206 visible_range,
1207 meta: None,
1208 }
1209 }
1210
1211 #[must_use]
1217 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1218 self.meta = meta.into_option();
1219 self
1220 }
1221}
1222
1223#[serde_as]
1227#[skip_serializing_none]
1228#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1229#[schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME))]
1230#[serde(rename_all = "camelCase")]
1231#[non_exhaustive]
1232pub struct StartNesRequest {
1233 pub workspace_uri: Option<String>,
1235 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1237 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1238 #[serde(default)]
1239 pub workspace_folders: Option<Vec<WorkspaceFolder>>,
1240 #[serde_as(deserialize_as = "DefaultOnError")]
1242 #[schemars(extend("x-deserialize-default-on-error" = true))]
1243 #[serde(default)]
1244 pub repository: Option<NesRepository>,
1245 #[serde(rename = "_meta")]
1251 pub meta: Option<Meta>,
1252}
1253
1254impl StartNesRequest {
1255 #[must_use]
1257 pub fn new() -> Self {
1258 Self {
1259 workspace_uri: None,
1260 workspace_folders: None,
1261 repository: None,
1262 meta: None,
1263 }
1264 }
1265
1266 #[must_use]
1268 pub fn workspace_uri(mut self, workspace_uri: impl IntoOption<String>) -> Self {
1269 self.workspace_uri = workspace_uri.into_option();
1270 self
1271 }
1272
1273 #[must_use]
1275 pub fn workspace_folders(
1276 mut self,
1277 workspace_folders: impl IntoOption<Vec<WorkspaceFolder>>,
1278 ) -> Self {
1279 self.workspace_folders = workspace_folders.into_option();
1280 self
1281 }
1282
1283 #[must_use]
1285 pub fn repository(mut self, repository: impl IntoOption<NesRepository>) -> Self {
1286 self.repository = repository.into_option();
1287 self
1288 }
1289
1290 #[must_use]
1296 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1297 self.meta = meta.into_option();
1298 self
1299 }
1300}
1301
1302impl Default for StartNesRequest {
1303 fn default() -> Self {
1304 Self::new()
1305 }
1306}
1307
1308#[skip_serializing_none]
1310#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1311#[serde(rename_all = "camelCase")]
1312#[non_exhaustive]
1313pub struct WorkspaceFolder {
1314 pub uri: String,
1316 pub name: String,
1318 #[serde(rename = "_meta")]
1324 pub meta: Option<Meta>,
1325}
1326
1327impl WorkspaceFolder {
1328 #[must_use]
1330 pub fn new(uri: impl Into<String>, name: impl Into<String>) -> Self {
1331 Self {
1332 uri: uri.into(),
1333 name: name.into(),
1334 meta: None,
1335 }
1336 }
1337
1338 #[must_use]
1344 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1345 self.meta = meta.into_option();
1346 self
1347 }
1348}
1349
1350#[skip_serializing_none]
1352#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1353#[serde(rename_all = "camelCase")]
1354#[non_exhaustive]
1355pub struct NesRepository {
1356 pub name: String,
1358 pub owner: String,
1360 pub remote_url: String,
1362 #[serde(rename = "_meta")]
1368 pub meta: Option<Meta>,
1369}
1370
1371impl NesRepository {
1372 #[must_use]
1374 pub fn new(
1375 name: impl Into<String>,
1376 owner: impl Into<String>,
1377 remote_url: impl Into<String>,
1378 ) -> Self {
1379 Self {
1380 name: name.into(),
1381 owner: owner.into(),
1382 remote_url: remote_url.into(),
1383 meta: None,
1384 }
1385 }
1386
1387 #[must_use]
1393 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1394 self.meta = meta.into_option();
1395 self
1396 }
1397}
1398
1399#[skip_serializing_none]
1401#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1402#[schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME))]
1403#[serde(rename_all = "camelCase")]
1404#[non_exhaustive]
1405pub struct StartNesResponse {
1406 pub session_id: SessionId,
1408 #[serde(rename = "_meta")]
1414 pub meta: Option<Meta>,
1415}
1416
1417impl StartNesResponse {
1418 #[must_use]
1420 pub fn new(session_id: impl Into<SessionId>) -> Self {
1421 Self {
1422 session_id: session_id.into(),
1423 meta: None,
1424 }
1425 }
1426
1427 #[must_use]
1433 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1434 self.meta = meta.into_option();
1435 self
1436 }
1437}
1438
1439#[skip_serializing_none]
1446#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1447#[schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME))]
1448#[serde(rename_all = "camelCase")]
1449#[non_exhaustive]
1450pub struct CloseNesRequest {
1451 pub session_id: SessionId,
1453 #[serde(rename = "_meta")]
1459 pub meta: Option<Meta>,
1460}
1461
1462impl CloseNesRequest {
1463 #[must_use]
1465 pub fn new(session_id: impl Into<SessionId>) -> Self {
1466 Self {
1467 session_id: session_id.into(),
1468 meta: None,
1469 }
1470 }
1471
1472 #[must_use]
1478 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1479 self.meta = meta.into_option();
1480 self
1481 }
1482}
1483
1484#[skip_serializing_none]
1486#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1487#[schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME))]
1488#[serde(rename_all = "camelCase")]
1489#[non_exhaustive]
1490pub struct CloseNesResponse {
1491 #[serde(rename = "_meta")]
1497 pub meta: Option<Meta>,
1498}
1499
1500impl CloseNesResponse {
1501 #[must_use]
1503 pub fn new() -> Self {
1504 Self::default()
1505 }
1506
1507 #[must_use]
1513 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1514 self.meta = meta.into_option();
1515 self
1516 }
1517}
1518
1519#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1523#[non_exhaustive]
1524pub enum NesTriggerKind {
1525 #[serde(rename = "automatic")]
1527 Automatic,
1528 #[serde(rename = "diagnostic")]
1530 Diagnostic,
1531 #[serde(rename = "manual")]
1533 Manual,
1534 #[serde(untagged)]
1540 Other(String),
1541}
1542
1543#[serde_as]
1545#[skip_serializing_none]
1546#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1547#[schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME))]
1548#[serde(rename_all = "camelCase")]
1549#[non_exhaustive]
1550pub struct SuggestNesRequest {
1551 pub session_id: SessionId,
1553 pub uri: String,
1555 pub version: i64,
1557 pub position: Position,
1559 #[serde_as(deserialize_as = "DefaultOnError")]
1561 #[schemars(extend("x-deserialize-default-on-error" = true))]
1562 #[serde(default)]
1563 pub selection: Option<Range>,
1564 pub trigger_kind: NesTriggerKind,
1566 #[serde_as(deserialize_as = "DefaultOnError")]
1568 #[schemars(extend("x-deserialize-default-on-error" = true))]
1569 #[serde(default)]
1570 pub context: Option<NesSuggestContext>,
1571 #[serde(rename = "_meta")]
1577 pub meta: Option<Meta>,
1578}
1579
1580impl SuggestNesRequest {
1581 #[must_use]
1583 pub fn new(
1584 session_id: impl Into<SessionId>,
1585 uri: impl Into<String>,
1586 version: i64,
1587 position: Position,
1588 trigger_kind: NesTriggerKind,
1589 ) -> Self {
1590 Self {
1591 session_id: session_id.into(),
1592 uri: uri.into(),
1593 version,
1594 position,
1595 selection: None,
1596 trigger_kind,
1597 context: None,
1598 meta: None,
1599 }
1600 }
1601
1602 #[must_use]
1604 pub fn selection(mut self, selection: impl IntoOption<Range>) -> Self {
1605 self.selection = selection.into_option();
1606 self
1607 }
1608
1609 #[must_use]
1611 pub fn context(mut self, context: impl IntoOption<NesSuggestContext>) -> Self {
1612 self.context = context.into_option();
1613 self
1614 }
1615
1616 #[must_use]
1622 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1623 self.meta = meta.into_option();
1624 self
1625 }
1626}
1627
1628#[serde_as]
1630#[skip_serializing_none]
1631#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1632#[serde(rename_all = "camelCase")]
1633#[non_exhaustive]
1634pub struct NesSuggestContext {
1635 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1637 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1638 #[serde(default)]
1639 pub recent_files: Option<Vec<NesRecentFile>>,
1640 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1642 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1643 #[serde(default)]
1644 pub related_snippets: Option<Vec<NesRelatedSnippet>>,
1645 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1647 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1648 #[serde(default)]
1649 pub edit_history: Option<Vec<NesEditHistoryEntry>>,
1650 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1652 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1653 #[serde(default)]
1654 pub user_actions: Option<Vec<NesUserAction>>,
1655 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1657 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1658 #[serde(default)]
1659 pub open_files: Option<Vec<NesOpenFile>>,
1660 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1662 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1663 #[serde(default)]
1664 pub diagnostics: Option<Vec<NesDiagnostic>>,
1665 #[serde(rename = "_meta")]
1671 pub meta: Option<Meta>,
1672}
1673
1674impl NesSuggestContext {
1675 #[must_use]
1677 pub fn new() -> Self {
1678 Self::default()
1679 }
1680
1681 #[must_use]
1683 pub fn recent_files(mut self, recent_files: impl IntoOption<Vec<NesRecentFile>>) -> Self {
1684 self.recent_files = recent_files.into_option();
1685 self
1686 }
1687
1688 #[must_use]
1690 pub fn related_snippets(
1691 mut self,
1692 related_snippets: impl IntoOption<Vec<NesRelatedSnippet>>,
1693 ) -> Self {
1694 self.related_snippets = related_snippets.into_option();
1695 self
1696 }
1697
1698 #[must_use]
1700 pub fn edit_history(mut self, edit_history: impl IntoOption<Vec<NesEditHistoryEntry>>) -> Self {
1701 self.edit_history = edit_history.into_option();
1702 self
1703 }
1704
1705 #[must_use]
1707 pub fn user_actions(mut self, user_actions: impl IntoOption<Vec<NesUserAction>>) -> Self {
1708 self.user_actions = user_actions.into_option();
1709 self
1710 }
1711
1712 #[must_use]
1714 pub fn open_files(mut self, open_files: impl IntoOption<Vec<NesOpenFile>>) -> Self {
1715 self.open_files = open_files.into_option();
1716 self
1717 }
1718
1719 #[must_use]
1721 pub fn diagnostics(mut self, diagnostics: impl IntoOption<Vec<NesDiagnostic>>) -> Self {
1722 self.diagnostics = diagnostics.into_option();
1723 self
1724 }
1725
1726 #[must_use]
1732 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1733 self.meta = meta.into_option();
1734 self
1735 }
1736}
1737
1738#[skip_serializing_none]
1740#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1741#[serde(rename_all = "camelCase")]
1742#[non_exhaustive]
1743pub struct NesRecentFile {
1744 pub uri: String,
1746 pub language_id: String,
1748 pub text: String,
1750 #[serde(rename = "_meta")]
1756 pub meta: Option<Meta>,
1757}
1758
1759impl NesRecentFile {
1760 #[must_use]
1762 pub fn new(
1763 uri: impl Into<String>,
1764 language_id: impl Into<String>,
1765 text: impl Into<String>,
1766 ) -> Self {
1767 Self {
1768 uri: uri.into(),
1769 language_id: language_id.into(),
1770 text: text.into(),
1771 meta: None,
1772 }
1773 }
1774
1775 #[must_use]
1781 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1782 self.meta = meta.into_option();
1783 self
1784 }
1785}
1786
1787#[skip_serializing_none]
1789#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1790#[serde(rename_all = "camelCase")]
1791#[non_exhaustive]
1792pub struct NesRelatedSnippet {
1793 pub uri: String,
1795 pub excerpts: Vec<NesExcerpt>,
1797 #[serde(rename = "_meta")]
1803 pub meta: Option<Meta>,
1804}
1805
1806impl NesRelatedSnippet {
1807 #[must_use]
1809 pub fn new(uri: impl Into<String>, excerpts: Vec<NesExcerpt>) -> Self {
1810 Self {
1811 uri: uri.into(),
1812 excerpts,
1813 meta: None,
1814 }
1815 }
1816
1817 #[must_use]
1823 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1824 self.meta = meta.into_option();
1825 self
1826 }
1827}
1828
1829#[skip_serializing_none]
1831#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1832#[serde(rename_all = "camelCase")]
1833#[non_exhaustive]
1834pub struct NesExcerpt {
1835 pub start_line: u32,
1837 pub end_line: u32,
1839 pub text: String,
1841 #[serde(rename = "_meta")]
1847 pub meta: Option<Meta>,
1848}
1849
1850impl NesExcerpt {
1851 #[must_use]
1853 pub fn new(start_line: u32, end_line: u32, text: impl Into<String>) -> Self {
1854 Self {
1855 start_line,
1856 end_line,
1857 text: text.into(),
1858 meta: None,
1859 }
1860 }
1861
1862 #[must_use]
1868 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1869 self.meta = meta.into_option();
1870 self
1871 }
1872}
1873
1874#[skip_serializing_none]
1876#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1877#[serde(rename_all = "camelCase")]
1878#[non_exhaustive]
1879pub struct NesEditHistoryEntry {
1880 pub uri: String,
1882 pub diff: String,
1884 #[serde(rename = "_meta")]
1890 pub meta: Option<Meta>,
1891}
1892
1893impl NesEditHistoryEntry {
1894 #[must_use]
1896 pub fn new(uri: impl Into<String>, diff: impl Into<String>) -> Self {
1897 Self {
1898 uri: uri.into(),
1899 diff: diff.into(),
1900 meta: None,
1901 }
1902 }
1903
1904 #[must_use]
1910 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1911 self.meta = meta.into_option();
1912 self
1913 }
1914}
1915
1916#[skip_serializing_none]
1918#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1919#[serde(rename_all = "camelCase")]
1920#[non_exhaustive]
1921pub struct NesUserAction {
1922 pub action: String,
1924 pub uri: String,
1926 pub position: Position,
1928 pub timestamp_ms: u64,
1930 #[serde(rename = "_meta")]
1936 pub meta: Option<Meta>,
1937}
1938
1939impl NesUserAction {
1940 #[must_use]
1942 pub fn new(
1943 action: impl Into<String>,
1944 uri: impl Into<String>,
1945 position: Position,
1946 timestamp_ms: u64,
1947 ) -> Self {
1948 Self {
1949 action: action.into(),
1950 uri: uri.into(),
1951 position,
1952 timestamp_ms,
1953 meta: None,
1954 }
1955 }
1956
1957 #[must_use]
1963 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1964 self.meta = meta.into_option();
1965 self
1966 }
1967}
1968
1969#[serde_as]
1971#[skip_serializing_none]
1972#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1973#[serde(rename_all = "camelCase")]
1974#[non_exhaustive]
1975pub struct NesOpenFile {
1976 pub uri: String,
1978 pub language_id: String,
1980 #[serde_as(deserialize_as = "DefaultOnError")]
1982 #[schemars(extend("x-deserialize-default-on-error" = true))]
1983 #[serde(default)]
1984 pub visible_range: Option<Range>,
1985 #[serde_as(deserialize_as = "DefaultOnError")]
1987 #[schemars(extend("x-deserialize-default-on-error" = true))]
1988 #[serde(default)]
1989 pub last_focused_ms: Option<u64>,
1990 #[serde(rename = "_meta")]
1996 pub meta: Option<Meta>,
1997}
1998
1999impl NesOpenFile {
2000 #[must_use]
2002 pub fn new(uri: impl Into<String>, language_id: impl Into<String>) -> Self {
2003 Self {
2004 uri: uri.into(),
2005 language_id: language_id.into(),
2006 visible_range: None,
2007 last_focused_ms: None,
2008 meta: None,
2009 }
2010 }
2011
2012 #[must_use]
2014 pub fn visible_range(mut self, visible_range: impl IntoOption<Range>) -> Self {
2015 self.visible_range = visible_range.into_option();
2016 self
2017 }
2018
2019 #[must_use]
2021 pub fn last_focused_ms(mut self, last_focused_ms: impl IntoOption<u64>) -> Self {
2022 self.last_focused_ms = last_focused_ms.into_option();
2023 self
2024 }
2025
2026 #[must_use]
2032 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2033 self.meta = meta.into_option();
2034 self
2035 }
2036}
2037
2038#[skip_serializing_none]
2040#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2041#[serde(rename_all = "camelCase")]
2042#[non_exhaustive]
2043pub struct NesDiagnostic {
2044 pub uri: String,
2046 pub range: Range,
2048 pub severity: NesDiagnosticSeverity,
2050 pub message: String,
2052 #[serde(rename = "_meta")]
2058 pub meta: Option<Meta>,
2059}
2060
2061impl NesDiagnostic {
2062 #[must_use]
2064 pub fn new(
2065 uri: impl Into<String>,
2066 range: Range,
2067 severity: NesDiagnosticSeverity,
2068 message: impl Into<String>,
2069 ) -> Self {
2070 Self {
2071 uri: uri.into(),
2072 range,
2073 severity,
2074 message: message.into(),
2075 meta: None,
2076 }
2077 }
2078
2079 #[must_use]
2085 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2086 self.meta = meta.into_option();
2087 self
2088 }
2089}
2090
2091#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2093#[non_exhaustive]
2094pub enum NesDiagnosticSeverity {
2095 #[serde(rename = "error")]
2097 Error,
2098 #[serde(rename = "warning")]
2100 Warning,
2101 #[serde(rename = "information")]
2103 Information,
2104 #[serde(rename = "hint")]
2106 Hint,
2107 #[serde(untagged)]
2113 Other(String),
2114}
2115
2116#[serde_as]
2120#[skip_serializing_none]
2121#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2122#[schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME))]
2123#[serde(rename_all = "camelCase")]
2124#[non_exhaustive]
2125pub struct SuggestNesResponse {
2126 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2128 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2129 pub suggestions: Vec<NesSuggestion>,
2130 #[serde(rename = "_meta")]
2136 pub meta: Option<Meta>,
2137}
2138
2139impl SuggestNesResponse {
2140 #[must_use]
2142 pub fn new(suggestions: Vec<NesSuggestion>) -> Self {
2143 Self {
2144 suggestions,
2145 meta: None,
2146 }
2147 }
2148
2149 #[must_use]
2155 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2156 self.meta = meta.into_option();
2157 self
2158 }
2159}
2160
2161#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2163#[serde(tag = "kind", rename_all = "camelCase")]
2164#[schemars(extend("discriminator" = {"propertyName": "kind"}))]
2165#[non_exhaustive]
2166pub enum NesSuggestion {
2167 Edit(NesEditSuggestion),
2169 Jump(NesJumpSuggestion),
2171 Rename(NesRenameSuggestion),
2173 SearchAndReplace(NesSearchAndReplaceSuggestion),
2175 #[serde(untagged)]
2185 Other(OtherNesSuggestion),
2186}
2187
2188#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2190#[schemars(inline)]
2191#[schemars(transform = other_nes_suggestion_schema)]
2192#[serde(rename_all = "camelCase")]
2193#[non_exhaustive]
2194pub struct OtherNesSuggestion {
2195 pub kind: String,
2201 #[serde(flatten)]
2203 pub fields: BTreeMap<String, serde_json::Value>,
2204}
2205
2206impl OtherNesSuggestion {
2207 #[must_use]
2209 pub fn new(kind: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2210 fields.remove("kind");
2211 Self {
2212 kind: kind.into(),
2213 fields,
2214 }
2215 }
2216}
2217
2218impl<'de> Deserialize<'de> for OtherNesSuggestion {
2219 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2220 where
2221 D: serde::Deserializer<'de>,
2222 {
2223 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2224 let kind = fields
2225 .remove("kind")
2226 .ok_or_else(|| serde::de::Error::missing_field("kind"))?;
2227 let serde_json::Value::String(kind) = kind else {
2228 return Err(serde::de::Error::custom("`kind` must be a string"));
2229 };
2230
2231 if is_known_nes_suggestion_kind(&kind) {
2232 return Err(serde::de::Error::custom(format!(
2233 "known NES suggestion `{kind}` did not match its schema"
2234 )));
2235 }
2236
2237 Ok(Self { kind, fields })
2238 }
2239}
2240
2241fn is_known_nes_suggestion_kind(kind: &str) -> bool {
2242 matches!(kind, "edit" | "jump" | "rename" | "searchAndReplace")
2243}
2244
2245fn other_nes_suggestion_schema(schema: &mut Schema) {
2246 super::schema_util::reject_known_string_discriminators(
2247 schema,
2248 "kind",
2249 &["edit", "jump", "rename", "searchAndReplace"],
2250 );
2251}
2252
2253#[serde_as]
2255#[skip_serializing_none]
2256#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2257#[serde(rename_all = "camelCase")]
2258#[non_exhaustive]
2259pub struct NesEditSuggestion {
2260 pub id: String,
2262 pub uri: String,
2264 pub edits: Vec<NesTextEdit>,
2266 #[serde_as(deserialize_as = "DefaultOnError")]
2268 #[schemars(extend("x-deserialize-default-on-error" = true))]
2269 #[serde(default)]
2270 pub cursor_position: Option<Position>,
2271 #[serde(rename = "_meta")]
2277 pub meta: Option<Meta>,
2278}
2279
2280impl NesEditSuggestion {
2281 #[must_use]
2283 pub fn new(id: impl Into<String>, uri: impl Into<String>, edits: Vec<NesTextEdit>) -> Self {
2284 Self {
2285 id: id.into(),
2286 uri: uri.into(),
2287 edits,
2288 cursor_position: None,
2289 meta: None,
2290 }
2291 }
2292
2293 #[must_use]
2295 pub fn cursor_position(mut self, cursor_position: impl IntoOption<Position>) -> Self {
2296 self.cursor_position = cursor_position.into_option();
2297 self
2298 }
2299
2300 #[must_use]
2306 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2307 self.meta = meta.into_option();
2308 self
2309 }
2310}
2311
2312#[skip_serializing_none]
2314#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2315#[serde(rename_all = "camelCase")]
2316#[non_exhaustive]
2317pub struct NesTextEdit {
2318 pub range: Range,
2320 pub new_text: String,
2322 #[serde(rename = "_meta")]
2328 pub meta: Option<Meta>,
2329}
2330
2331impl NesTextEdit {
2332 #[must_use]
2334 pub fn new(range: Range, new_text: impl Into<String>) -> Self {
2335 Self {
2336 range,
2337 new_text: new_text.into(),
2338 meta: None,
2339 }
2340 }
2341
2342 #[must_use]
2348 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2349 self.meta = meta.into_option();
2350 self
2351 }
2352}
2353
2354#[skip_serializing_none]
2356#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2357#[serde(rename_all = "camelCase")]
2358#[non_exhaustive]
2359pub struct NesJumpSuggestion {
2360 pub id: String,
2362 pub uri: String,
2364 pub position: Position,
2366 #[serde(rename = "_meta")]
2372 pub meta: Option<Meta>,
2373}
2374
2375impl NesJumpSuggestion {
2376 #[must_use]
2378 pub fn new(id: impl Into<String>, uri: impl Into<String>, position: Position) -> Self {
2379 Self {
2380 id: id.into(),
2381 uri: uri.into(),
2382 position,
2383 meta: None,
2384 }
2385 }
2386
2387 #[must_use]
2393 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2394 self.meta = meta.into_option();
2395 self
2396 }
2397}
2398
2399#[skip_serializing_none]
2401#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2402#[serde(rename_all = "camelCase")]
2403#[non_exhaustive]
2404pub struct NesRenameSuggestion {
2405 pub id: String,
2407 pub uri: String,
2409 pub position: Position,
2411 pub new_name: String,
2413 #[serde(rename = "_meta")]
2419 pub meta: Option<Meta>,
2420}
2421
2422impl NesRenameSuggestion {
2423 #[must_use]
2425 pub fn new(
2426 id: impl Into<String>,
2427 uri: impl Into<String>,
2428 position: Position,
2429 new_name: impl Into<String>,
2430 ) -> Self {
2431 Self {
2432 id: id.into(),
2433 uri: uri.into(),
2434 position,
2435 new_name: new_name.into(),
2436 meta: None,
2437 }
2438 }
2439
2440 #[must_use]
2446 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2447 self.meta = meta.into_option();
2448 self
2449 }
2450}
2451
2452#[skip_serializing_none]
2454#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2455#[serde(rename_all = "camelCase")]
2456#[non_exhaustive]
2457pub struct NesSearchAndReplaceSuggestion {
2458 pub id: String,
2460 pub uri: String,
2462 pub search: String,
2464 pub replace: String,
2466 pub is_regex: Option<bool>,
2468 #[serde(rename = "_meta")]
2474 pub meta: Option<Meta>,
2475}
2476
2477impl NesSearchAndReplaceSuggestion {
2478 #[must_use]
2480 pub fn new(
2481 id: impl Into<String>,
2482 uri: impl Into<String>,
2483 search: impl Into<String>,
2484 replace: impl Into<String>,
2485 ) -> Self {
2486 Self {
2487 id: id.into(),
2488 uri: uri.into(),
2489 search: search.into(),
2490 replace: replace.into(),
2491 is_regex: None,
2492 meta: None,
2493 }
2494 }
2495
2496 #[must_use]
2498 pub fn is_regex(mut self, is_regex: impl IntoOption<bool>) -> Self {
2499 self.is_regex = is_regex.into_option();
2500 self
2501 }
2502
2503 #[must_use]
2509 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2510 self.meta = meta.into_option();
2511 self
2512 }
2513}
2514
2515#[skip_serializing_none]
2519#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2520#[schemars(extend("x-side" = "agent", "x-method" = NES_ACCEPT_METHOD_NAME))]
2521#[serde(rename_all = "camelCase")]
2522#[non_exhaustive]
2523pub struct AcceptNesNotification {
2524 pub session_id: SessionId,
2526 pub id: String,
2528 #[serde(rename = "_meta")]
2534 pub meta: Option<Meta>,
2535}
2536
2537impl AcceptNesNotification {
2538 #[must_use]
2540 pub fn new(session_id: impl Into<SessionId>, id: impl Into<String>) -> Self {
2541 Self {
2542 session_id: session_id.into(),
2543 id: id.into(),
2544 meta: None,
2545 }
2546 }
2547
2548 #[must_use]
2554 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2555 self.meta = meta.into_option();
2556 self
2557 }
2558}
2559
2560#[serde_as]
2562#[skip_serializing_none]
2563#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2564#[schemars(extend("x-side" = "agent", "x-method" = NES_REJECT_METHOD_NAME))]
2565#[serde(rename_all = "camelCase")]
2566#[non_exhaustive]
2567pub struct RejectNesNotification {
2568 pub session_id: SessionId,
2570 pub id: String,
2572 #[serde_as(deserialize_as = "DefaultOnError")]
2574 #[schemars(extend("x-deserialize-default-on-error" = true))]
2575 #[serde(default)]
2576 pub reason: Option<NesRejectReason>,
2577 #[serde(rename = "_meta")]
2583 pub meta: Option<Meta>,
2584}
2585
2586impl RejectNesNotification {
2587 #[must_use]
2589 pub fn new(session_id: impl Into<SessionId>, id: impl Into<String>) -> Self {
2590 Self {
2591 session_id: session_id.into(),
2592 id: id.into(),
2593 reason: None,
2594 meta: None,
2595 }
2596 }
2597
2598 #[must_use]
2600 pub fn reason(mut self, reason: impl IntoOption<NesRejectReason>) -> Self {
2601 self.reason = reason.into_option();
2602 self
2603 }
2604
2605 #[must_use]
2611 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2612 self.meta = meta.into_option();
2613 self
2614 }
2615}
2616
2617#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2619#[non_exhaustive]
2620pub enum NesRejectReason {
2621 #[serde(rename = "rejected")]
2623 Rejected,
2624 #[serde(rename = "ignored")]
2626 Ignored,
2627 #[serde(rename = "replaced")]
2629 Replaced,
2630 #[serde(rename = "cancelled")]
2632 Cancelled,
2633 #[serde(untagged)]
2639 Other(String),
2640}
2641
2642#[cfg(test)]
2643mod tests {
2644 use super::*;
2645 use serde_json::json;
2646
2647 #[test]
2648 fn test_position_encoding_kind_serialization() {
2649 assert_eq!(
2650 serde_json::to_value(&PositionEncodingKind::Utf16).unwrap(),
2651 json!("utf-16")
2652 );
2653 assert_eq!(
2654 serde_json::to_value(&PositionEncodingKind::Utf32).unwrap(),
2655 json!("utf-32")
2656 );
2657 assert_eq!(
2658 serde_json::to_value(&PositionEncodingKind::Utf8).unwrap(),
2659 json!("utf-8")
2660 );
2661
2662 assert_eq!(
2663 serde_json::from_value::<PositionEncodingKind>(json!("utf-16")).unwrap(),
2664 PositionEncodingKind::Utf16
2665 );
2666 assert_eq!(
2667 serde_json::from_value::<PositionEncodingKind>(json!("utf-32")).unwrap(),
2668 PositionEncodingKind::Utf32
2669 );
2670 assert_eq!(
2671 serde_json::from_value::<PositionEncodingKind>(json!("utf-8")).unwrap(),
2672 PositionEncodingKind::Utf8
2673 );
2674 assert!(serde_json::from_value::<PositionEncodingKind>(json!("_future")).is_err());
2675 }
2676
2677 #[test]
2678 fn test_client_capabilities_skip_unknown_position_encodings() {
2679 let caps: crate::v2::ClientCapabilities = serde_json::from_value(json!({
2680 "positionEncodings": ["_future", "utf-8", "utf-16"]
2681 }))
2682 .unwrap();
2683
2684 assert_eq!(
2685 caps.position_encodings,
2686 vec![PositionEncodingKind::Utf8, PositionEncodingKind::Utf16]
2687 );
2688 }
2689
2690 #[test]
2691 fn test_agent_nes_capabilities_serialization() {
2692 let caps = NesCapabilities::new()
2693 .events(
2694 NesEventCapabilities::new().document(
2695 NesDocumentEventCapabilities::new()
2696 .did_open(NesDocumentDidOpenCapabilities::default())
2697 .did_change(NesDocumentDidChangeCapabilities::new(
2698 TextDocumentSyncKind::Incremental,
2699 ))
2700 .did_close(NesDocumentDidCloseCapabilities::default())
2701 .did_save(NesDocumentDidSaveCapabilities::default())
2702 .did_focus(NesDocumentDidFocusCapabilities::default()),
2703 ),
2704 )
2705 .context(
2706 NesContextCapabilities::new()
2707 .recent_files(NesRecentFilesCapabilities {
2708 max_count: Some(10),
2709 meta: None,
2710 })
2711 .related_snippets(NesRelatedSnippetsCapabilities::default())
2712 .edit_history(NesEditHistoryCapabilities {
2713 max_count: Some(6),
2714 meta: None,
2715 })
2716 .user_actions(NesUserActionsCapabilities {
2717 max_count: Some(16),
2718 meta: None,
2719 })
2720 .open_files(NesOpenFilesCapabilities::default())
2721 .diagnostics(NesDiagnosticsCapabilities::default()),
2722 );
2723
2724 let json = serde_json::to_value(&caps).unwrap();
2725 assert_eq!(
2726 json,
2727 json!({
2728 "events": {
2729 "document": {
2730 "didOpen": {},
2731 "didChange": {
2732 "syncKind": "incremental"
2733 },
2734 "didClose": {},
2735 "didSave": {},
2736 "didFocus": {}
2737 }
2738 },
2739 "context": {
2740 "recentFiles": {
2741 "maxCount": 10
2742 },
2743 "relatedSnippets": {},
2744 "editHistory": {
2745 "maxCount": 6
2746 },
2747 "userActions": {
2748 "maxCount": 16
2749 },
2750 "openFiles": {},
2751 "diagnostics": {}
2752 }
2753 })
2754 );
2755
2756 let deserialized: NesCapabilities = serde_json::from_value(json).unwrap();
2758 assert_eq!(deserialized, caps);
2759 }
2760
2761 #[test]
2762 fn test_client_nes_capabilities_serialization() {
2763 let caps = ClientNesCapabilities::new()
2764 .jump(NesJumpCapabilities::default())
2765 .rename(NesRenameCapabilities::default())
2766 .search_and_replace(NesSearchAndReplaceCapabilities::default());
2767
2768 let json = serde_json::to_value(&caps).unwrap();
2769 assert_eq!(
2770 json,
2771 json!({
2772 "jump": {},
2773 "rename": {},
2774 "searchAndReplace": {}
2775 })
2776 );
2777
2778 let deserialized: ClientNesCapabilities = serde_json::from_value(json).unwrap();
2779 assert_eq!(deserialized, caps);
2780 }
2781
2782 #[test]
2783 fn test_document_did_open_serialization() {
2784 let notification = DidOpenDocumentNotification::new(
2785 "session_123",
2786 "file:///path/to/file.rs",
2787 "rust",
2788 1,
2789 "fn main() {\n println!(\"hello\");\n}\n",
2790 );
2791
2792 let json = serde_json::to_value(¬ification).unwrap();
2793 assert_eq!(
2794 json,
2795 json!({
2796 "sessionId": "session_123",
2797 "uri": "file:///path/to/file.rs",
2798 "languageId": "rust",
2799 "version": 1,
2800 "text": "fn main() {\n println!(\"hello\");\n}\n"
2801 })
2802 );
2803
2804 let deserialized: DidOpenDocumentNotification = serde_json::from_value(json).unwrap();
2805 assert_eq!(deserialized, notification);
2806 }
2807
2808 #[test]
2809 fn test_document_did_change_incremental_serialization() {
2810 let notification = DidChangeDocumentNotification::new(
2811 "session_123",
2812 "file:///path/to/file.rs",
2813 2,
2814 vec![TextDocumentContentChangeEvent::incremental(
2815 Range::new(Position::new(1, 4), Position::new(1, 4)),
2816 "let x = 42;\n ",
2817 )],
2818 );
2819
2820 let json = serde_json::to_value(¬ification).unwrap();
2821 assert_eq!(
2822 json,
2823 json!({
2824 "sessionId": "session_123",
2825 "uri": "file:///path/to/file.rs",
2826 "version": 2,
2827 "contentChanges": [
2828 {
2829 "range": {
2830 "start": { "line": 1, "character": 4 },
2831 "end": { "line": 1, "character": 4 }
2832 },
2833 "text": "let x = 42;\n "
2834 }
2835 ]
2836 })
2837 );
2838 }
2839
2840 #[test]
2841 fn test_document_did_change_full_serialization() {
2842 let notification = DidChangeDocumentNotification::new(
2843 "session_123",
2844 "file:///path/to/file.rs",
2845 2,
2846 vec![TextDocumentContentChangeEvent::full(
2847 "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n",
2848 )],
2849 );
2850
2851 let json = serde_json::to_value(¬ification).unwrap();
2852 assert_eq!(
2853 json,
2854 json!({
2855 "sessionId": "session_123",
2856 "uri": "file:///path/to/file.rs",
2857 "version": 2,
2858 "contentChanges": [
2859 {
2860 "text": "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n"
2861 }
2862 ]
2863 })
2864 );
2865 }
2866
2867 #[test]
2868 fn test_document_did_close_serialization() {
2869 let notification =
2870 DidCloseDocumentNotification::new("session_123", "file:///path/to/file.rs");
2871 let json = serde_json::to_value(¬ification).unwrap();
2872 assert_eq!(
2873 json,
2874 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
2875 );
2876 }
2877
2878 #[test]
2879 fn test_document_did_save_serialization() {
2880 let notification =
2881 DidSaveDocumentNotification::new("session_123", "file:///path/to/file.rs");
2882 let json = serde_json::to_value(¬ification).unwrap();
2883 assert_eq!(
2884 json,
2885 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
2886 );
2887 }
2888
2889 #[test]
2890 fn test_document_did_focus_serialization() {
2891 let notification = DidFocusDocumentNotification::new(
2892 "session_123",
2893 "file:///path/to/file.rs",
2894 2,
2895 Position::new(5, 12),
2896 Range::new(Position::new(0, 0), Position::new(45, 0)),
2897 );
2898
2899 let json = serde_json::to_value(¬ification).unwrap();
2900 assert_eq!(
2901 json,
2902 json!({
2903 "sessionId": "session_123",
2904 "uri": "file:///path/to/file.rs",
2905 "version": 2,
2906 "position": { "line": 5, "character": 12 },
2907 "visibleRange": {
2908 "start": { "line": 0, "character": 0 },
2909 "end": { "line": 45, "character": 0 }
2910 }
2911 })
2912 );
2913 }
2914
2915 #[test]
2916 fn test_nes_suggestion_edit_serialization() {
2917 let suggestion = NesSuggestion::Edit(
2918 NesEditSuggestion::new(
2919 "sugg_001",
2920 "file:///path/to/other_file.rs",
2921 vec![NesTextEdit::new(
2922 Range::new(Position::new(5, 0), Position::new(5, 10)),
2923 "let result = helper();",
2924 )],
2925 )
2926 .cursor_position(Position::new(5, 22)),
2927 );
2928
2929 let json = serde_json::to_value(&suggestion).unwrap();
2930 assert_eq!(
2931 json,
2932 json!({
2933 "kind": "edit",
2934 "id": "sugg_001",
2935 "uri": "file:///path/to/other_file.rs",
2936 "edits": [
2937 {
2938 "range": {
2939 "start": { "line": 5, "character": 0 },
2940 "end": { "line": 5, "character": 10 }
2941 },
2942 "newText": "let result = helper();"
2943 }
2944 ],
2945 "cursorPosition": { "line": 5, "character": 22 }
2946 })
2947 );
2948
2949 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
2950 assert_eq!(deserialized, suggestion);
2951 }
2952
2953 #[test]
2954 fn test_nes_suggestion_unknown_variant() {
2955 let suggestion: NesSuggestion = serde_json::from_value(json!({
2956 "kind": "_preview",
2957 "id": "sugg_001",
2958 "label": "Preview generated file"
2959 }))
2960 .unwrap();
2961
2962 let NesSuggestion::Other(unknown) = suggestion else {
2963 panic!("expected unknown NES suggestion");
2964 };
2965
2966 assert_eq!(unknown.kind, "_preview");
2967 assert_eq!(unknown.fields.get("id"), Some(&json!("sugg_001")));
2968 assert_eq!(
2969 serde_json::to_value(NesSuggestion::Other(unknown)).unwrap(),
2970 json!({
2971 "kind": "_preview",
2972 "id": "sugg_001",
2973 "label": "Preview generated file"
2974 })
2975 );
2976 }
2977
2978 #[test]
2979 fn test_nes_suggestion_unknown_does_not_hide_malformed_known_variant() {
2980 assert!(
2981 serde_json::from_value::<NesSuggestion>(json!({
2982 "kind": "edit"
2983 }))
2984 .is_err()
2985 );
2986 }
2987
2988 #[test]
2989 fn test_nes_suggestion_jump_serialization() {
2990 let suggestion = NesSuggestion::Jump(NesJumpSuggestion::new(
2991 "sugg_002",
2992 "file:///path/to/other_file.rs",
2993 Position::new(15, 4),
2994 ));
2995
2996 let json = serde_json::to_value(&suggestion).unwrap();
2997 assert_eq!(
2998 json,
2999 json!({
3000 "kind": "jump",
3001 "id": "sugg_002",
3002 "uri": "file:///path/to/other_file.rs",
3003 "position": { "line": 15, "character": 4 }
3004 })
3005 );
3006
3007 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3008 assert_eq!(deserialized, suggestion);
3009 }
3010
3011 #[test]
3012 fn test_nes_suggestion_rename_serialization() {
3013 let suggestion = NesSuggestion::Rename(NesRenameSuggestion::new(
3014 "sugg_003",
3015 "file:///path/to/file.rs",
3016 Position::new(5, 10),
3017 "calculateTotal",
3018 ));
3019
3020 let json = serde_json::to_value(&suggestion).unwrap();
3021 assert_eq!(
3022 json,
3023 json!({
3024 "kind": "rename",
3025 "id": "sugg_003",
3026 "uri": "file:///path/to/file.rs",
3027 "position": { "line": 5, "character": 10 },
3028 "newName": "calculateTotal"
3029 })
3030 );
3031
3032 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3033 assert_eq!(deserialized, suggestion);
3034 }
3035
3036 #[test]
3037 fn test_nes_suggestion_search_and_replace_serialization() {
3038 let suggestion = NesSuggestion::SearchAndReplace(
3039 NesSearchAndReplaceSuggestion::new(
3040 "sugg_004",
3041 "file:///path/to/file.rs",
3042 "oldFunction",
3043 "newFunction",
3044 )
3045 .is_regex(false),
3046 );
3047
3048 let json = serde_json::to_value(&suggestion).unwrap();
3049 assert_eq!(
3050 json,
3051 json!({
3052 "kind": "searchAndReplace",
3053 "id": "sugg_004",
3054 "uri": "file:///path/to/file.rs",
3055 "search": "oldFunction",
3056 "replace": "newFunction",
3057 "isRegex": false
3058 })
3059 );
3060
3061 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3062 assert_eq!(deserialized, suggestion);
3063 }
3064
3065 #[test]
3066 fn test_nes_start_request_serialization() {
3067 let request = StartNesRequest::new()
3068 .workspace_uri("file:///Users/alice/projects/my-app")
3069 .workspace_folders(vec![WorkspaceFolder::new(
3070 "file:///Users/alice/projects/my-app",
3071 "my-app",
3072 )])
3073 .repository(NesRepository::new(
3074 "my-app",
3075 "alice",
3076 "https://github.com/alice/my-app.git",
3077 ));
3078
3079 let json = serde_json::to_value(&request).unwrap();
3080 assert_eq!(
3081 json,
3082 json!({
3083 "workspaceUri": "file:///Users/alice/projects/my-app",
3084 "workspaceFolders": [
3085 {
3086 "uri": "file:///Users/alice/projects/my-app",
3087 "name": "my-app"
3088 }
3089 ],
3090 "repository": {
3091 "name": "my-app",
3092 "owner": "alice",
3093 "remoteUrl": "https://github.com/alice/my-app.git"
3094 }
3095 })
3096 );
3097 }
3098
3099 #[test]
3100 fn test_nes_start_response_serialization() {
3101 let response = StartNesResponse::new("session_abc123");
3102 let json = serde_json::to_value(&response).unwrap();
3103 assert_eq!(json, json!({ "sessionId": "session_abc123" }));
3104 }
3105
3106 #[test]
3107 fn test_nes_trigger_kind_serialization() {
3108 assert_eq!(
3109 serde_json::to_value(&NesTriggerKind::Automatic).unwrap(),
3110 json!("automatic")
3111 );
3112 assert_eq!(
3113 serde_json::to_value(&NesTriggerKind::Diagnostic).unwrap(),
3114 json!("diagnostic")
3115 );
3116 assert_eq!(
3117 serde_json::to_value(&NesTriggerKind::Manual).unwrap(),
3118 json!("manual")
3119 );
3120 }
3121
3122 #[test]
3123 fn test_nes_reject_reason_serialization() {
3124 assert_eq!(
3125 serde_json::to_value(&NesRejectReason::Rejected).unwrap(),
3126 json!("rejected")
3127 );
3128 assert_eq!(
3129 serde_json::to_value(&NesRejectReason::Ignored).unwrap(),
3130 json!("ignored")
3131 );
3132 assert_eq!(
3133 serde_json::to_value(&NesRejectReason::Replaced).unwrap(),
3134 json!("replaced")
3135 );
3136 assert_eq!(
3137 serde_json::to_value(&NesRejectReason::Cancelled).unwrap(),
3138 json!("cancelled")
3139 );
3140 }
3141
3142 #[test]
3143 fn test_nes_accept_notification_serialization() {
3144 let notification = AcceptNesNotification::new("session_123", "sugg_001");
3145 let json = serde_json::to_value(¬ification).unwrap();
3146 assert_eq!(
3147 json,
3148 json!({ "sessionId": "session_123", "id": "sugg_001" })
3149 );
3150 }
3151
3152 #[test]
3153 fn test_nes_reject_notification_serialization() {
3154 let notification =
3155 RejectNesNotification::new("session_123", "sugg_001").reason(NesRejectReason::Rejected);
3156 let json = serde_json::to_value(¬ification).unwrap();
3157 assert_eq!(
3158 json,
3159 json!({ "sessionId": "session_123", "id": "sugg_001", "reason": "rejected" })
3160 );
3161 }
3162
3163 #[test]
3164 fn test_nes_suggest_request_with_context_serialization() {
3165 let request = SuggestNesRequest::new(
3166 "session_123",
3167 "file:///path/to/file.rs",
3168 2,
3169 Position::new(5, 12),
3170 NesTriggerKind::Automatic,
3171 )
3172 .selection(Range::new(Position::new(5, 4), Position::new(5, 12)))
3173 .context(
3174 NesSuggestContext::new()
3175 .recent_files(vec![NesRecentFile::new(
3176 "file:///path/to/utils.rs",
3177 "rust",
3178 "pub fn helper() -> i32 { 42 }\n",
3179 )])
3180 .diagnostics(vec![NesDiagnostic::new(
3181 "file:///path/to/file.rs",
3182 Range::new(Position::new(5, 0), Position::new(5, 10)),
3183 NesDiagnosticSeverity::Error,
3184 "cannot find value `foo` in this scope",
3185 )]),
3186 );
3187
3188 let json = serde_json::to_value(&request).unwrap();
3189 assert_eq!(json["sessionId"], "session_123");
3190 assert_eq!(json["uri"], "file:///path/to/file.rs");
3191 assert_eq!(json["version"], 2);
3192 assert_eq!(json["triggerKind"], "automatic");
3193 assert_eq!(
3194 json["context"]["recentFiles"][0]["uri"],
3195 "file:///path/to/utils.rs"
3196 );
3197 assert_eq!(json["context"]["diagnostics"][0]["severity"], "error");
3198 }
3199
3200 #[test]
3201 fn test_text_document_sync_kind_serialization() {
3202 assert_eq!(
3203 serde_json::to_value(&TextDocumentSyncKind::Full).unwrap(),
3204 json!("full")
3205 );
3206 assert_eq!(
3207 serde_json::to_value(&TextDocumentSyncKind::Incremental).unwrap(),
3208 json!("incremental")
3209 );
3210 assert!(serde_json::from_value::<TextDocumentSyncKind>(json!("_future")).is_err());
3211 }
3212
3213 #[test]
3214 fn test_document_event_capabilities_drop_unknown_did_change_sync_kind() {
3215 let caps: NesDocumentEventCapabilities = serde_json::from_value(json!({
3216 "didChange": {
3217 "syncKind": "_future"
3218 }
3219 }))
3220 .unwrap();
3221
3222 assert_eq!(caps.did_change, None);
3223 }
3224
3225 #[test]
3226 fn test_document_did_change_capabilities_requires_sync_kind() {
3227 assert!(serde_json::from_value::<NesDocumentDidChangeCapabilities>(json!({})).is_err());
3228 }
3229
3230 #[test]
3231 fn test_nes_suggest_response_serialization() {
3232 let response = SuggestNesResponse::new(vec![
3233 NesSuggestion::Edit(NesEditSuggestion::new(
3234 "sugg_001",
3235 "file:///path/to/file.rs",
3236 vec![NesTextEdit::new(
3237 Range::new(Position::new(5, 0), Position::new(5, 10)),
3238 "let result = helper();",
3239 )],
3240 )),
3241 NesSuggestion::Jump(NesJumpSuggestion::new(
3242 "sugg_002",
3243 "file:///path/to/other.rs",
3244 Position::new(10, 0),
3245 )),
3246 ]);
3247
3248 let json = serde_json::to_value(&response).unwrap();
3249 assert_eq!(json["suggestions"].as_array().unwrap().len(), 2);
3250 assert_eq!(json["suggestions"][0]["kind"], "edit");
3251 assert_eq!(json["suggestions"][1]["kind"], "jump");
3252 }
3253}