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]
81 pub fn new(line: u32, character: u32) -> Self {
82 Self {
83 line,
84 character,
85 meta: None,
86 }
87 }
88
89 #[must_use]
95 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
96 self.meta = meta.into_option();
97 self
98 }
99}
100
101#[skip_serializing_none]
103#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
104#[serde(rename_all = "camelCase")]
105#[non_exhaustive]
106pub struct Range {
107 pub start: Position,
109 pub end: Position,
111 #[serde(rename = "_meta")]
117 pub meta: Option<Meta>,
118}
119
120impl Range {
121 #[must_use]
122 pub fn new(start: Position, end: Position) -> Self {
123 Self {
124 start,
125 end,
126 meta: None,
127 }
128 }
129
130 #[must_use]
136 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
137 self.meta = meta.into_option();
138 self
139 }
140}
141
142#[serde_as]
149#[skip_serializing_none]
150#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
151#[serde(rename_all = "camelCase")]
152#[non_exhaustive]
153pub struct NesCapabilities {
154 #[serde_as(deserialize_as = "DefaultOnError")]
156 #[schemars(extend("x-deserialize-default-on-error" = true))]
157 #[serde(default)]
158 pub events: Option<NesEventCapabilities>,
159 #[serde_as(deserialize_as = "DefaultOnError")]
161 #[schemars(extend("x-deserialize-default-on-error" = true))]
162 #[serde(default)]
163 pub context: Option<NesContextCapabilities>,
164 #[serde(rename = "_meta")]
170 pub meta: Option<Meta>,
171}
172
173impl NesCapabilities {
174 #[must_use]
175 pub fn new() -> Self {
176 Self::default()
177 }
178
179 #[must_use]
180 pub fn events(mut self, events: impl IntoOption<NesEventCapabilities>) -> Self {
181 self.events = events.into_option();
182 self
183 }
184
185 #[must_use]
186 pub fn context(mut self, context: impl IntoOption<NesContextCapabilities>) -> Self {
187 self.context = context.into_option();
188 self
189 }
190
191 #[must_use]
197 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
198 self.meta = meta.into_option();
199 self
200 }
201}
202
203#[serde_as]
205#[skip_serializing_none]
206#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
207#[serde(rename_all = "camelCase")]
208#[non_exhaustive]
209pub struct NesEventCapabilities {
210 #[serde_as(deserialize_as = "DefaultOnError")]
212 #[schemars(extend("x-deserialize-default-on-error" = true))]
213 #[serde(default)]
214 pub document: Option<NesDocumentEventCapabilities>,
215 #[serde(rename = "_meta")]
221 pub meta: Option<Meta>,
222}
223
224impl NesEventCapabilities {
225 #[must_use]
226 pub fn new() -> Self {
227 Self::default()
228 }
229
230 #[must_use]
231 pub fn document(mut self, document: impl IntoOption<NesDocumentEventCapabilities>) -> Self {
232 self.document = document.into_option();
233 self
234 }
235
236 #[must_use]
242 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
243 self.meta = meta.into_option();
244 self
245 }
246}
247
248#[serde_as]
250#[skip_serializing_none]
251#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
252#[serde(rename_all = "camelCase")]
253#[non_exhaustive]
254pub struct NesDocumentEventCapabilities {
255 #[serde_as(deserialize_as = "DefaultOnError")]
257 #[schemars(extend("x-deserialize-default-on-error" = true))]
258 #[serde(default)]
259 pub did_open: Option<NesDocumentDidOpenCapabilities>,
260 #[serde_as(deserialize_as = "DefaultOnError")]
262 #[schemars(extend("x-deserialize-default-on-error" = true))]
263 #[serde(default)]
264 pub did_change: Option<NesDocumentDidChangeCapabilities>,
265 #[serde_as(deserialize_as = "DefaultOnError")]
267 #[schemars(extend("x-deserialize-default-on-error" = true))]
268 #[serde(default)]
269 pub did_close: Option<NesDocumentDidCloseCapabilities>,
270 #[serde_as(deserialize_as = "DefaultOnError")]
272 #[schemars(extend("x-deserialize-default-on-error" = true))]
273 #[serde(default)]
274 pub did_save: Option<NesDocumentDidSaveCapabilities>,
275 #[serde_as(deserialize_as = "DefaultOnError")]
277 #[schemars(extend("x-deserialize-default-on-error" = true))]
278 #[serde(default)]
279 pub did_focus: Option<NesDocumentDidFocusCapabilities>,
280 #[serde(rename = "_meta")]
286 pub meta: Option<Meta>,
287}
288
289impl NesDocumentEventCapabilities {
290 #[must_use]
291 pub fn new() -> Self {
292 Self::default()
293 }
294
295 #[must_use]
296 pub fn did_open(mut self, did_open: impl IntoOption<NesDocumentDidOpenCapabilities>) -> Self {
297 self.did_open = did_open.into_option();
298 self
299 }
300
301 #[must_use]
302 pub fn did_change(
303 mut self,
304 did_change: impl IntoOption<NesDocumentDidChangeCapabilities>,
305 ) -> Self {
306 self.did_change = did_change.into_option();
307 self
308 }
309
310 #[must_use]
311 pub fn did_close(
312 mut self,
313 did_close: impl IntoOption<NesDocumentDidCloseCapabilities>,
314 ) -> Self {
315 self.did_close = did_close.into_option();
316 self
317 }
318
319 #[must_use]
320 pub fn did_save(mut self, did_save: impl IntoOption<NesDocumentDidSaveCapabilities>) -> Self {
321 self.did_save = did_save.into_option();
322 self
323 }
324
325 #[must_use]
326 pub fn did_focus(
327 mut self,
328 did_focus: impl IntoOption<NesDocumentDidFocusCapabilities>,
329 ) -> Self {
330 self.did_focus = did_focus.into_option();
331 self
332 }
333
334 #[must_use]
340 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
341 self.meta = meta.into_option();
342 self
343 }
344}
345
346#[skip_serializing_none]
348#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
349#[serde(rename_all = "camelCase")]
350#[non_exhaustive]
351pub struct NesDocumentDidOpenCapabilities {
352 #[serde(rename = "_meta")]
358 pub meta: Option<Meta>,
359}
360
361impl NesDocumentDidOpenCapabilities {
362 #[must_use]
363 pub fn new() -> Self {
364 Self::default()
365 }
366}
367
368#[skip_serializing_none]
370#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
371#[serde(rename_all = "camelCase")]
372#[non_exhaustive]
373pub struct NesDocumentDidChangeCapabilities {
374 pub sync_kind: TextDocumentSyncKind,
376 #[serde(rename = "_meta")]
382 pub meta: Option<Meta>,
383}
384
385impl NesDocumentDidChangeCapabilities {
386 #[must_use]
387 pub fn new(sync_kind: TextDocumentSyncKind) -> Self {
388 Self {
389 sync_kind,
390 meta: None,
391 }
392 }
393
394 #[must_use]
400 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
401 self.meta = meta.into_option();
402 self
403 }
404}
405
406#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
408#[non_exhaustive]
409pub enum TextDocumentSyncKind {
410 #[serde(rename = "full")]
412 Full,
413 #[serde(rename = "incremental")]
415 Incremental,
416}
417
418#[skip_serializing_none]
420#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
421#[serde(rename_all = "camelCase")]
422#[non_exhaustive]
423pub struct NesDocumentDidCloseCapabilities {
424 #[serde(rename = "_meta")]
430 pub meta: Option<Meta>,
431}
432
433impl NesDocumentDidCloseCapabilities {
434 #[must_use]
435 pub fn new() -> Self {
436 Self::default()
437 }
438}
439
440#[skip_serializing_none]
442#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
443#[serde(rename_all = "camelCase")]
444#[non_exhaustive]
445pub struct NesDocumentDidSaveCapabilities {
446 #[serde(rename = "_meta")]
452 pub meta: Option<Meta>,
453}
454
455impl NesDocumentDidSaveCapabilities {
456 #[must_use]
457 pub fn new() -> Self {
458 Self::default()
459 }
460}
461
462#[skip_serializing_none]
464#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
465#[serde(rename_all = "camelCase")]
466#[non_exhaustive]
467pub struct NesDocumentDidFocusCapabilities {
468 #[serde(rename = "_meta")]
474 pub meta: Option<Meta>,
475}
476
477impl NesDocumentDidFocusCapabilities {
478 #[must_use]
479 pub fn new() -> Self {
480 Self::default()
481 }
482}
483
484#[serde_as]
486#[skip_serializing_none]
487#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
488#[serde(rename_all = "camelCase")]
489#[non_exhaustive]
490pub struct NesContextCapabilities {
491 #[serde_as(deserialize_as = "DefaultOnError")]
493 #[schemars(extend("x-deserialize-default-on-error" = true))]
494 #[serde(default)]
495 pub recent_files: Option<NesRecentFilesCapabilities>,
496 #[serde_as(deserialize_as = "DefaultOnError")]
498 #[schemars(extend("x-deserialize-default-on-error" = true))]
499 #[serde(default)]
500 pub related_snippets: Option<NesRelatedSnippetsCapabilities>,
501 #[serde_as(deserialize_as = "DefaultOnError")]
503 #[schemars(extend("x-deserialize-default-on-error" = true))]
504 #[serde(default)]
505 pub edit_history: Option<NesEditHistoryCapabilities>,
506 #[serde_as(deserialize_as = "DefaultOnError")]
508 #[schemars(extend("x-deserialize-default-on-error" = true))]
509 #[serde(default)]
510 pub user_actions: Option<NesUserActionsCapabilities>,
511 #[serde_as(deserialize_as = "DefaultOnError")]
513 #[schemars(extend("x-deserialize-default-on-error" = true))]
514 #[serde(default)]
515 pub open_files: Option<NesOpenFilesCapabilities>,
516 #[serde_as(deserialize_as = "DefaultOnError")]
518 #[schemars(extend("x-deserialize-default-on-error" = true))]
519 #[serde(default)]
520 pub diagnostics: Option<NesDiagnosticsCapabilities>,
521 #[serde(rename = "_meta")]
527 pub meta: Option<Meta>,
528}
529
530impl NesContextCapabilities {
531 #[must_use]
532 pub fn new() -> Self {
533 Self::default()
534 }
535
536 #[must_use]
537 pub fn recent_files(
538 mut self,
539 recent_files: impl IntoOption<NesRecentFilesCapabilities>,
540 ) -> Self {
541 self.recent_files = recent_files.into_option();
542 self
543 }
544
545 #[must_use]
546 pub fn related_snippets(
547 mut self,
548 related_snippets: impl IntoOption<NesRelatedSnippetsCapabilities>,
549 ) -> Self {
550 self.related_snippets = related_snippets.into_option();
551 self
552 }
553
554 #[must_use]
555 pub fn edit_history(
556 mut self,
557 edit_history: impl IntoOption<NesEditHistoryCapabilities>,
558 ) -> Self {
559 self.edit_history = edit_history.into_option();
560 self
561 }
562
563 #[must_use]
564 pub fn user_actions(
565 mut self,
566 user_actions: impl IntoOption<NesUserActionsCapabilities>,
567 ) -> Self {
568 self.user_actions = user_actions.into_option();
569 self
570 }
571
572 #[must_use]
573 pub fn open_files(mut self, open_files: impl IntoOption<NesOpenFilesCapabilities>) -> Self {
574 self.open_files = open_files.into_option();
575 self
576 }
577
578 #[must_use]
579 pub fn diagnostics(mut self, diagnostics: impl IntoOption<NesDiagnosticsCapabilities>) -> Self {
580 self.diagnostics = diagnostics.into_option();
581 self
582 }
583
584 #[must_use]
590 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
591 self.meta = meta.into_option();
592 self
593 }
594}
595
596#[skip_serializing_none]
598#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
599#[serde(rename_all = "camelCase")]
600#[non_exhaustive]
601pub struct NesRecentFilesCapabilities {
602 pub max_count: Option<u32>,
604 #[serde(rename = "_meta")]
610 pub meta: Option<Meta>,
611}
612
613impl NesRecentFilesCapabilities {
614 #[must_use]
615 pub fn new() -> Self {
616 Self::default()
617 }
618}
619
620#[skip_serializing_none]
622#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
623#[serde(rename_all = "camelCase")]
624#[non_exhaustive]
625pub struct NesRelatedSnippetsCapabilities {
626 #[serde(rename = "_meta")]
632 pub meta: Option<Meta>,
633}
634
635impl NesRelatedSnippetsCapabilities {
636 #[must_use]
637 pub fn new() -> Self {
638 Self::default()
639 }
640}
641
642#[skip_serializing_none]
644#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
645#[serde(rename_all = "camelCase")]
646#[non_exhaustive]
647pub struct NesEditHistoryCapabilities {
648 pub max_count: Option<u32>,
650 #[serde(rename = "_meta")]
656 pub meta: Option<Meta>,
657}
658
659impl NesEditHistoryCapabilities {
660 #[must_use]
661 pub fn new() -> Self {
662 Self::default()
663 }
664}
665
666#[skip_serializing_none]
668#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
669#[serde(rename_all = "camelCase")]
670#[non_exhaustive]
671pub struct NesUserActionsCapabilities {
672 pub max_count: Option<u32>,
674 #[serde(rename = "_meta")]
680 pub meta: Option<Meta>,
681}
682
683impl NesUserActionsCapabilities {
684 #[must_use]
685 pub fn new() -> Self {
686 Self::default()
687 }
688}
689
690#[skip_serializing_none]
692#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
693#[serde(rename_all = "camelCase")]
694#[non_exhaustive]
695pub struct NesOpenFilesCapabilities {
696 #[serde(rename = "_meta")]
702 pub meta: Option<Meta>,
703}
704
705impl NesOpenFilesCapabilities {
706 #[must_use]
707 pub fn new() -> Self {
708 Self::default()
709 }
710}
711
712#[skip_serializing_none]
714#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
715#[serde(rename_all = "camelCase")]
716#[non_exhaustive]
717pub struct NesDiagnosticsCapabilities {
718 #[serde(rename = "_meta")]
724 pub meta: Option<Meta>,
725}
726
727impl NesDiagnosticsCapabilities {
728 #[must_use]
729 pub fn new() -> Self {
730 Self::default()
731 }
732}
733
734#[serde_as]
738#[skip_serializing_none]
739#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
740#[serde(rename_all = "camelCase")]
741#[non_exhaustive]
742pub struct ClientNesCapabilities {
743 #[serde_as(deserialize_as = "DefaultOnError")]
745 #[schemars(extend("x-deserialize-default-on-error" = true))]
746 #[serde(default)]
747 pub jump: Option<NesJumpCapabilities>,
748 #[serde_as(deserialize_as = "DefaultOnError")]
750 #[schemars(extend("x-deserialize-default-on-error" = true))]
751 #[serde(default)]
752 pub rename: Option<NesRenameCapabilities>,
753 #[serde_as(deserialize_as = "DefaultOnError")]
755 #[schemars(extend("x-deserialize-default-on-error" = true))]
756 #[serde(default)]
757 pub search_and_replace: Option<NesSearchAndReplaceCapabilities>,
758 #[serde(rename = "_meta")]
764 pub meta: Option<Meta>,
765}
766
767impl ClientNesCapabilities {
768 #[must_use]
769 pub fn new() -> Self {
770 Self::default()
771 }
772
773 #[must_use]
774 pub fn jump(mut self, jump: impl IntoOption<NesJumpCapabilities>) -> Self {
775 self.jump = jump.into_option();
776 self
777 }
778
779 #[must_use]
780 pub fn rename(mut self, rename: impl IntoOption<NesRenameCapabilities>) -> Self {
781 self.rename = rename.into_option();
782 self
783 }
784
785 #[must_use]
786 pub fn search_and_replace(
787 mut self,
788 search_and_replace: impl IntoOption<NesSearchAndReplaceCapabilities>,
789 ) -> Self {
790 self.search_and_replace = search_and_replace.into_option();
791 self
792 }
793
794 #[must_use]
800 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
801 self.meta = meta.into_option();
802 self
803 }
804}
805
806#[skip_serializing_none]
808#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
809#[serde(rename_all = "camelCase")]
810#[non_exhaustive]
811pub struct NesJumpCapabilities {
812 #[serde(rename = "_meta")]
818 pub meta: Option<Meta>,
819}
820
821impl NesJumpCapabilities {
822 #[must_use]
823 pub fn new() -> Self {
824 Self::default()
825 }
826}
827
828#[skip_serializing_none]
830#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
831#[serde(rename_all = "camelCase")]
832#[non_exhaustive]
833pub struct NesRenameCapabilities {
834 #[serde(rename = "_meta")]
840 pub meta: Option<Meta>,
841}
842
843impl NesRenameCapabilities {
844 #[must_use]
845 pub fn new() -> Self {
846 Self::default()
847 }
848}
849
850#[skip_serializing_none]
852#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
853#[serde(rename_all = "camelCase")]
854#[non_exhaustive]
855pub struct NesSearchAndReplaceCapabilities {
856 #[serde(rename = "_meta")]
862 pub meta: Option<Meta>,
863}
864
865impl NesSearchAndReplaceCapabilities {
866 #[must_use]
867 pub fn new() -> Self {
868 Self::default()
869 }
870}
871
872#[skip_serializing_none]
876#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
877#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_OPEN_METHOD_NAME))]
878#[serde(rename_all = "camelCase")]
879#[non_exhaustive]
880pub struct DidOpenDocumentNotification {
881 pub session_id: SessionId,
883 pub uri: String,
885 pub language_id: String,
887 pub version: i64,
889 pub text: String,
891 #[serde(rename = "_meta")]
897 pub meta: Option<Meta>,
898}
899
900impl DidOpenDocumentNotification {
901 #[must_use]
902 pub fn new(
903 session_id: impl Into<SessionId>,
904 uri: impl Into<String>,
905 language_id: impl Into<String>,
906 version: i64,
907 text: impl Into<String>,
908 ) -> Self {
909 Self {
910 session_id: session_id.into(),
911 uri: uri.into(),
912 language_id: language_id.into(),
913 version,
914 text: text.into(),
915 meta: None,
916 }
917 }
918
919 #[must_use]
925 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
926 self.meta = meta.into_option();
927 self
928 }
929}
930
931#[skip_serializing_none]
933#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
934#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CHANGE_METHOD_NAME))]
935#[serde(rename_all = "camelCase")]
936#[non_exhaustive]
937pub struct DidChangeDocumentNotification {
938 pub session_id: SessionId,
940 pub uri: String,
942 pub version: i64,
944 pub content_changes: Vec<TextDocumentContentChangeEvent>,
946 #[serde(rename = "_meta")]
952 pub meta: Option<Meta>,
953}
954
955impl DidChangeDocumentNotification {
956 #[must_use]
957 pub fn new(
958 session_id: impl Into<SessionId>,
959 uri: impl Into<String>,
960 version: i64,
961 content_changes: Vec<TextDocumentContentChangeEvent>,
962 ) -> Self {
963 Self {
964 session_id: session_id.into(),
965 uri: uri.into(),
966 version,
967 content_changes,
968 meta: None,
969 }
970 }
971
972 #[must_use]
978 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
979 self.meta = meta.into_option();
980 self
981 }
982}
983
984#[skip_serializing_none]
989#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
990#[serde(rename_all = "camelCase")]
991#[non_exhaustive]
992pub struct TextDocumentContentChangeEvent {
993 pub range: Option<Range>,
995 pub text: String,
997 #[serde(rename = "_meta")]
1003 pub meta: Option<Meta>,
1004}
1005
1006impl TextDocumentContentChangeEvent {
1007 #[must_use]
1008 pub fn full(text: impl Into<String>) -> Self {
1009 Self {
1010 range: None,
1011 text: text.into(),
1012 meta: None,
1013 }
1014 }
1015
1016 #[must_use]
1017 pub fn incremental(range: Range, text: impl Into<String>) -> Self {
1018 Self {
1019 range: Some(range),
1020 text: text.into(),
1021 meta: None,
1022 }
1023 }
1024
1025 #[must_use]
1031 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1032 self.meta = meta.into_option();
1033 self
1034 }
1035}
1036
1037#[skip_serializing_none]
1039#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1040#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CLOSE_METHOD_NAME))]
1041#[serde(rename_all = "camelCase")]
1042#[non_exhaustive]
1043pub struct DidCloseDocumentNotification {
1044 pub session_id: SessionId,
1046 pub uri: String,
1048 #[serde(rename = "_meta")]
1054 pub meta: Option<Meta>,
1055}
1056
1057impl DidCloseDocumentNotification {
1058 #[must_use]
1059 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1060 Self {
1061 session_id: session_id.into(),
1062 uri: uri.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_SAVE_METHOD_NAME))]
1083#[serde(rename_all = "camelCase")]
1084#[non_exhaustive]
1085pub struct DidSaveDocumentNotification {
1086 pub session_id: SessionId,
1088 pub uri: String,
1090 #[serde(rename = "_meta")]
1096 pub meta: Option<Meta>,
1097}
1098
1099impl DidSaveDocumentNotification {
1100 #[must_use]
1101 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1102 Self {
1103 session_id: session_id.into(),
1104 uri: uri.into(),
1105 meta: None,
1106 }
1107 }
1108
1109 #[must_use]
1115 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1116 self.meta = meta.into_option();
1117 self
1118 }
1119}
1120
1121#[skip_serializing_none]
1123#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1124#[schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_FOCUS_METHOD_NAME))]
1125#[serde(rename_all = "camelCase")]
1126#[non_exhaustive]
1127pub struct DidFocusDocumentNotification {
1128 pub session_id: SessionId,
1130 pub uri: String,
1132 pub version: i64,
1134 pub position: Position,
1136 pub visible_range: Range,
1138 #[serde(rename = "_meta")]
1144 pub meta: Option<Meta>,
1145}
1146
1147impl DidFocusDocumentNotification {
1148 #[must_use]
1149 pub fn new(
1150 session_id: impl Into<SessionId>,
1151 uri: impl Into<String>,
1152 version: i64,
1153 position: Position,
1154 visible_range: Range,
1155 ) -> Self {
1156 Self {
1157 session_id: session_id.into(),
1158 uri: uri.into(),
1159 version,
1160 position,
1161 visible_range,
1162 meta: None,
1163 }
1164 }
1165
1166 #[must_use]
1172 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1173 self.meta = meta.into_option();
1174 self
1175 }
1176}
1177
1178#[serde_as]
1182#[skip_serializing_none]
1183#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1184#[schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME))]
1185#[serde(rename_all = "camelCase")]
1186#[non_exhaustive]
1187pub struct StartNesRequest {
1188 pub workspace_uri: Option<String>,
1190 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1192 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1193 #[serde(default)]
1194 pub workspace_folders: Option<Vec<WorkspaceFolder>>,
1195 #[serde_as(deserialize_as = "DefaultOnError")]
1197 #[schemars(extend("x-deserialize-default-on-error" = true))]
1198 #[serde(default)]
1199 pub repository: Option<NesRepository>,
1200 #[serde(rename = "_meta")]
1206 pub meta: Option<Meta>,
1207}
1208
1209impl StartNesRequest {
1210 #[must_use]
1211 pub fn new() -> Self {
1212 Self {
1213 workspace_uri: None,
1214 workspace_folders: None,
1215 repository: None,
1216 meta: None,
1217 }
1218 }
1219
1220 #[must_use]
1221 pub fn workspace_uri(mut self, workspace_uri: impl IntoOption<String>) -> Self {
1222 self.workspace_uri = workspace_uri.into_option();
1223 self
1224 }
1225
1226 #[must_use]
1227 pub fn workspace_folders(
1228 mut self,
1229 workspace_folders: impl IntoOption<Vec<WorkspaceFolder>>,
1230 ) -> Self {
1231 self.workspace_folders = workspace_folders.into_option();
1232 self
1233 }
1234
1235 #[must_use]
1236 pub fn repository(mut self, repository: impl IntoOption<NesRepository>) -> Self {
1237 self.repository = repository.into_option();
1238 self
1239 }
1240
1241 #[must_use]
1247 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1248 self.meta = meta.into_option();
1249 self
1250 }
1251}
1252
1253impl Default for StartNesRequest {
1254 fn default() -> Self {
1255 Self::new()
1256 }
1257}
1258
1259#[skip_serializing_none]
1261#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1262#[serde(rename_all = "camelCase")]
1263#[non_exhaustive]
1264pub struct WorkspaceFolder {
1265 pub uri: String,
1267 pub name: String,
1269 #[serde(rename = "_meta")]
1275 pub meta: Option<Meta>,
1276}
1277
1278impl WorkspaceFolder {
1279 #[must_use]
1280 pub fn new(uri: impl Into<String>, name: impl Into<String>) -> Self {
1281 Self {
1282 uri: uri.into(),
1283 name: name.into(),
1284 meta: None,
1285 }
1286 }
1287
1288 #[must_use]
1294 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1295 self.meta = meta.into_option();
1296 self
1297 }
1298}
1299
1300#[skip_serializing_none]
1302#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1303#[serde(rename_all = "camelCase")]
1304#[non_exhaustive]
1305pub struct NesRepository {
1306 pub name: String,
1308 pub owner: String,
1310 pub remote_url: String,
1312 #[serde(rename = "_meta")]
1318 pub meta: Option<Meta>,
1319}
1320
1321impl NesRepository {
1322 #[must_use]
1323 pub fn new(
1324 name: impl Into<String>,
1325 owner: impl Into<String>,
1326 remote_url: impl Into<String>,
1327 ) -> Self {
1328 Self {
1329 name: name.into(),
1330 owner: owner.into(),
1331 remote_url: remote_url.into(),
1332 meta: None,
1333 }
1334 }
1335
1336 #[must_use]
1342 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1343 self.meta = meta.into_option();
1344 self
1345 }
1346}
1347
1348#[skip_serializing_none]
1350#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1351#[schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME))]
1352#[serde(rename_all = "camelCase")]
1353#[non_exhaustive]
1354pub struct StartNesResponse {
1355 pub session_id: SessionId,
1357 #[serde(rename = "_meta")]
1363 pub meta: Option<Meta>,
1364}
1365
1366impl StartNesResponse {
1367 #[must_use]
1368 pub fn new(session_id: impl Into<SessionId>) -> Self {
1369 Self {
1370 session_id: session_id.into(),
1371 meta: None,
1372 }
1373 }
1374
1375 #[must_use]
1381 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1382 self.meta = meta.into_option();
1383 self
1384 }
1385}
1386
1387#[skip_serializing_none]
1394#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1395#[schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME))]
1396#[serde(rename_all = "camelCase")]
1397#[non_exhaustive]
1398pub struct CloseNesRequest {
1399 pub session_id: SessionId,
1401 #[serde(rename = "_meta")]
1407 pub meta: Option<Meta>,
1408}
1409
1410impl CloseNesRequest {
1411 #[must_use]
1412 pub fn new(session_id: impl Into<SessionId>) -> Self {
1413 Self {
1414 session_id: session_id.into(),
1415 meta: None,
1416 }
1417 }
1418
1419 #[must_use]
1425 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1426 self.meta = meta.into_option();
1427 self
1428 }
1429}
1430
1431#[skip_serializing_none]
1433#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1434#[schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME))]
1435#[serde(rename_all = "camelCase")]
1436#[non_exhaustive]
1437pub struct CloseNesResponse {
1438 #[serde(rename = "_meta")]
1444 pub meta: Option<Meta>,
1445}
1446
1447impl CloseNesResponse {
1448 #[must_use]
1449 pub fn new() -> Self {
1450 Self::default()
1451 }
1452
1453 #[must_use]
1459 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1460 self.meta = meta.into_option();
1461 self
1462 }
1463}
1464
1465#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1469#[non_exhaustive]
1470pub enum NesTriggerKind {
1471 #[serde(rename = "automatic")]
1473 Automatic,
1474 #[serde(rename = "diagnostic")]
1476 Diagnostic,
1477 #[serde(rename = "manual")]
1479 Manual,
1480 #[serde(untagged)]
1486 Other(String),
1487}
1488
1489#[serde_as]
1491#[skip_serializing_none]
1492#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1493#[schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME))]
1494#[serde(rename_all = "camelCase")]
1495#[non_exhaustive]
1496pub struct SuggestNesRequest {
1497 pub session_id: SessionId,
1499 pub uri: String,
1501 pub version: i64,
1503 pub position: Position,
1505 #[serde_as(deserialize_as = "DefaultOnError")]
1507 #[schemars(extend("x-deserialize-default-on-error" = true))]
1508 #[serde(default)]
1509 pub selection: Option<Range>,
1510 pub trigger_kind: NesTriggerKind,
1512 #[serde_as(deserialize_as = "DefaultOnError")]
1514 #[schemars(extend("x-deserialize-default-on-error" = true))]
1515 #[serde(default)]
1516 pub context: Option<NesSuggestContext>,
1517 #[serde(rename = "_meta")]
1523 pub meta: Option<Meta>,
1524}
1525
1526impl SuggestNesRequest {
1527 #[must_use]
1528 pub fn new(
1529 session_id: impl Into<SessionId>,
1530 uri: impl Into<String>,
1531 version: i64,
1532 position: Position,
1533 trigger_kind: NesTriggerKind,
1534 ) -> Self {
1535 Self {
1536 session_id: session_id.into(),
1537 uri: uri.into(),
1538 version,
1539 position,
1540 selection: None,
1541 trigger_kind,
1542 context: None,
1543 meta: None,
1544 }
1545 }
1546
1547 #[must_use]
1548 pub fn selection(mut self, selection: impl IntoOption<Range>) -> Self {
1549 self.selection = selection.into_option();
1550 self
1551 }
1552
1553 #[must_use]
1554 pub fn context(mut self, context: impl IntoOption<NesSuggestContext>) -> Self {
1555 self.context = context.into_option();
1556 self
1557 }
1558
1559 #[must_use]
1565 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1566 self.meta = meta.into_option();
1567 self
1568 }
1569}
1570
1571#[serde_as]
1573#[skip_serializing_none]
1574#[derive(Default, Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1575#[serde(rename_all = "camelCase")]
1576#[non_exhaustive]
1577pub struct NesSuggestContext {
1578 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1580 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1581 #[serde(default)]
1582 pub recent_files: Option<Vec<NesRecentFile>>,
1583 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1585 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1586 #[serde(default)]
1587 pub related_snippets: Option<Vec<NesRelatedSnippet>>,
1588 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1590 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1591 #[serde(default)]
1592 pub edit_history: Option<Vec<NesEditHistoryEntry>>,
1593 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1595 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1596 #[serde(default)]
1597 pub user_actions: Option<Vec<NesUserAction>>,
1598 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1600 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1601 #[serde(default)]
1602 pub open_files: Option<Vec<NesOpenFile>>,
1603 #[serde_as(deserialize_as = "DefaultOnError<Option<VecSkipError<_, SkipListener>>>")]
1605 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
1606 #[serde(default)]
1607 pub diagnostics: Option<Vec<NesDiagnostic>>,
1608 #[serde(rename = "_meta")]
1614 pub meta: Option<Meta>,
1615}
1616
1617impl NesSuggestContext {
1618 #[must_use]
1619 pub fn new() -> Self {
1620 Self::default()
1621 }
1622
1623 #[must_use]
1624 pub fn recent_files(mut self, recent_files: impl IntoOption<Vec<NesRecentFile>>) -> Self {
1625 self.recent_files = recent_files.into_option();
1626 self
1627 }
1628
1629 #[must_use]
1630 pub fn related_snippets(
1631 mut self,
1632 related_snippets: impl IntoOption<Vec<NesRelatedSnippet>>,
1633 ) -> Self {
1634 self.related_snippets = related_snippets.into_option();
1635 self
1636 }
1637
1638 #[must_use]
1639 pub fn edit_history(mut self, edit_history: impl IntoOption<Vec<NesEditHistoryEntry>>) -> Self {
1640 self.edit_history = edit_history.into_option();
1641 self
1642 }
1643
1644 #[must_use]
1645 pub fn user_actions(mut self, user_actions: impl IntoOption<Vec<NesUserAction>>) -> Self {
1646 self.user_actions = user_actions.into_option();
1647 self
1648 }
1649
1650 #[must_use]
1651 pub fn open_files(mut self, open_files: impl IntoOption<Vec<NesOpenFile>>) -> Self {
1652 self.open_files = open_files.into_option();
1653 self
1654 }
1655
1656 #[must_use]
1657 pub fn diagnostics(mut self, diagnostics: impl IntoOption<Vec<NesDiagnostic>>) -> Self {
1658 self.diagnostics = diagnostics.into_option();
1659 self
1660 }
1661
1662 #[must_use]
1668 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1669 self.meta = meta.into_option();
1670 self
1671 }
1672}
1673
1674#[skip_serializing_none]
1676#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1677#[serde(rename_all = "camelCase")]
1678#[non_exhaustive]
1679pub struct NesRecentFile {
1680 pub uri: String,
1682 pub language_id: String,
1684 pub text: String,
1686 #[serde(rename = "_meta")]
1692 pub meta: Option<Meta>,
1693}
1694
1695impl NesRecentFile {
1696 #[must_use]
1697 pub fn new(
1698 uri: impl Into<String>,
1699 language_id: impl Into<String>,
1700 text: impl Into<String>,
1701 ) -> Self {
1702 Self {
1703 uri: uri.into(),
1704 language_id: language_id.into(),
1705 text: text.into(),
1706 meta: None,
1707 }
1708 }
1709
1710 #[must_use]
1716 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1717 self.meta = meta.into_option();
1718 self
1719 }
1720}
1721
1722#[skip_serializing_none]
1724#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1725#[serde(rename_all = "camelCase")]
1726#[non_exhaustive]
1727pub struct NesRelatedSnippet {
1728 pub uri: String,
1730 pub excerpts: Vec<NesExcerpt>,
1732 #[serde(rename = "_meta")]
1738 pub meta: Option<Meta>,
1739}
1740
1741impl NesRelatedSnippet {
1742 #[must_use]
1743 pub fn new(uri: impl Into<String>, excerpts: Vec<NesExcerpt>) -> Self {
1744 Self {
1745 uri: uri.into(),
1746 excerpts,
1747 meta: None,
1748 }
1749 }
1750
1751 #[must_use]
1757 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1758 self.meta = meta.into_option();
1759 self
1760 }
1761}
1762
1763#[skip_serializing_none]
1765#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1766#[serde(rename_all = "camelCase")]
1767#[non_exhaustive]
1768pub struct NesExcerpt {
1769 pub start_line: u32,
1771 pub end_line: u32,
1773 pub text: String,
1775 #[serde(rename = "_meta")]
1781 pub meta: Option<Meta>,
1782}
1783
1784impl NesExcerpt {
1785 #[must_use]
1786 pub fn new(start_line: u32, end_line: u32, text: impl Into<String>) -> Self {
1787 Self {
1788 start_line,
1789 end_line,
1790 text: text.into(),
1791 meta: None,
1792 }
1793 }
1794
1795 #[must_use]
1801 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1802 self.meta = meta.into_option();
1803 self
1804 }
1805}
1806
1807#[skip_serializing_none]
1809#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1810#[serde(rename_all = "camelCase")]
1811#[non_exhaustive]
1812pub struct NesEditHistoryEntry {
1813 pub uri: String,
1815 pub diff: String,
1817 #[serde(rename = "_meta")]
1823 pub meta: Option<Meta>,
1824}
1825
1826impl NesEditHistoryEntry {
1827 #[must_use]
1828 pub fn new(uri: impl Into<String>, diff: impl Into<String>) -> Self {
1829 Self {
1830 uri: uri.into(),
1831 diff: diff.into(),
1832 meta: None,
1833 }
1834 }
1835
1836 #[must_use]
1842 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1843 self.meta = meta.into_option();
1844 self
1845 }
1846}
1847
1848#[skip_serializing_none]
1850#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1851#[serde(rename_all = "camelCase")]
1852#[non_exhaustive]
1853pub struct NesUserAction {
1854 pub action: String,
1856 pub uri: String,
1858 pub position: Position,
1860 pub timestamp_ms: u64,
1862 #[serde(rename = "_meta")]
1868 pub meta: Option<Meta>,
1869}
1870
1871impl NesUserAction {
1872 #[must_use]
1873 pub fn new(
1874 action: impl Into<String>,
1875 uri: impl Into<String>,
1876 position: Position,
1877 timestamp_ms: u64,
1878 ) -> Self {
1879 Self {
1880 action: action.into(),
1881 uri: uri.into(),
1882 position,
1883 timestamp_ms,
1884 meta: None,
1885 }
1886 }
1887
1888 #[must_use]
1894 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1895 self.meta = meta.into_option();
1896 self
1897 }
1898}
1899
1900#[serde_as]
1902#[skip_serializing_none]
1903#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1904#[serde(rename_all = "camelCase")]
1905#[non_exhaustive]
1906pub struct NesOpenFile {
1907 pub uri: String,
1909 pub language_id: String,
1911 #[serde_as(deserialize_as = "DefaultOnError")]
1913 #[schemars(extend("x-deserialize-default-on-error" = true))]
1914 #[serde(default)]
1915 pub visible_range: Option<Range>,
1916 #[serde_as(deserialize_as = "DefaultOnError")]
1918 #[schemars(extend("x-deserialize-default-on-error" = true))]
1919 #[serde(default)]
1920 pub last_focused_ms: Option<u64>,
1921 #[serde(rename = "_meta")]
1927 pub meta: Option<Meta>,
1928}
1929
1930impl NesOpenFile {
1931 #[must_use]
1932 pub fn new(uri: impl Into<String>, language_id: impl Into<String>) -> Self {
1933 Self {
1934 uri: uri.into(),
1935 language_id: language_id.into(),
1936 visible_range: None,
1937 last_focused_ms: None,
1938 meta: None,
1939 }
1940 }
1941
1942 #[must_use]
1943 pub fn visible_range(mut self, visible_range: impl IntoOption<Range>) -> Self {
1944 self.visible_range = visible_range.into_option();
1945 self
1946 }
1947
1948 #[must_use]
1949 pub fn last_focused_ms(mut self, last_focused_ms: impl IntoOption<u64>) -> Self {
1950 self.last_focused_ms = last_focused_ms.into_option();
1951 self
1952 }
1953
1954 #[must_use]
1960 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1961 self.meta = meta.into_option();
1962 self
1963 }
1964}
1965
1966#[skip_serializing_none]
1968#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
1969#[serde(rename_all = "camelCase")]
1970#[non_exhaustive]
1971pub struct NesDiagnostic {
1972 pub uri: String,
1974 pub range: Range,
1976 pub severity: NesDiagnosticSeverity,
1978 pub message: String,
1980 #[serde(rename = "_meta")]
1986 pub meta: Option<Meta>,
1987}
1988
1989impl NesDiagnostic {
1990 #[must_use]
1991 pub fn new(
1992 uri: impl Into<String>,
1993 range: Range,
1994 severity: NesDiagnosticSeverity,
1995 message: impl Into<String>,
1996 ) -> Self {
1997 Self {
1998 uri: uri.into(),
1999 range,
2000 severity,
2001 message: message.into(),
2002 meta: None,
2003 }
2004 }
2005
2006 #[must_use]
2012 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2013 self.meta = meta.into_option();
2014 self
2015 }
2016}
2017
2018#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2020#[non_exhaustive]
2021pub enum NesDiagnosticSeverity {
2022 #[serde(rename = "error")]
2024 Error,
2025 #[serde(rename = "warning")]
2027 Warning,
2028 #[serde(rename = "information")]
2030 Information,
2031 #[serde(rename = "hint")]
2033 Hint,
2034 #[serde(untagged)]
2040 Other(String),
2041}
2042
2043#[serde_as]
2047#[skip_serializing_none]
2048#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2049#[schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME))]
2050#[serde(rename_all = "camelCase")]
2051#[non_exhaustive]
2052pub struct SuggestNesResponse {
2053 #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
2055 #[schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true))]
2056 pub suggestions: Vec<NesSuggestion>,
2057 #[serde(rename = "_meta")]
2063 pub meta: Option<Meta>,
2064}
2065
2066impl SuggestNesResponse {
2067 #[must_use]
2068 pub fn new(suggestions: Vec<NesSuggestion>) -> Self {
2069 Self {
2070 suggestions,
2071 meta: None,
2072 }
2073 }
2074
2075 #[must_use]
2081 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2082 self.meta = meta.into_option();
2083 self
2084 }
2085}
2086
2087#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2089#[serde(tag = "kind", rename_all = "camelCase")]
2090#[schemars(extend("discriminator" = {"propertyName": "kind"}))]
2091#[non_exhaustive]
2092pub enum NesSuggestion {
2093 Edit(NesEditSuggestion),
2095 Jump(NesJumpSuggestion),
2097 Rename(NesRenameSuggestion),
2099 SearchAndReplace(NesSearchAndReplaceSuggestion),
2101 #[serde(untagged)]
2111 Other(OtherNesSuggestion),
2112}
2113
2114#[derive(Debug, Clone, Serialize, JsonSchema, PartialEq, Eq)]
2116#[schemars(inline)]
2117#[schemars(transform = other_nes_suggestion_schema)]
2118#[serde(rename_all = "camelCase")]
2119#[non_exhaustive]
2120pub struct OtherNesSuggestion {
2121 pub kind: String,
2127 #[serde(flatten)]
2129 pub fields: BTreeMap<String, serde_json::Value>,
2130}
2131
2132impl OtherNesSuggestion {
2133 #[must_use]
2134 pub fn new(kind: impl Into<String>, mut fields: BTreeMap<String, serde_json::Value>) -> Self {
2135 fields.remove("kind");
2136 Self {
2137 kind: kind.into(),
2138 fields,
2139 }
2140 }
2141}
2142
2143impl<'de> Deserialize<'de> for OtherNesSuggestion {
2144 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2145 where
2146 D: serde::Deserializer<'de>,
2147 {
2148 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2149 let kind = fields
2150 .remove("kind")
2151 .ok_or_else(|| serde::de::Error::missing_field("kind"))?;
2152 let serde_json::Value::String(kind) = kind else {
2153 return Err(serde::de::Error::custom("`kind` must be a string"));
2154 };
2155
2156 if is_known_nes_suggestion_kind(&kind) {
2157 return Err(serde::de::Error::custom(format!(
2158 "known NES suggestion `{kind}` did not match its schema"
2159 )));
2160 }
2161
2162 Ok(Self { kind, fields })
2163 }
2164}
2165
2166fn is_known_nes_suggestion_kind(kind: &str) -> bool {
2167 matches!(kind, "edit" | "jump" | "rename" | "searchAndReplace")
2168}
2169
2170fn other_nes_suggestion_schema(schema: &mut Schema) {
2171 super::schema_util::reject_known_string_discriminators(
2172 schema,
2173 "kind",
2174 &["edit", "jump", "rename", "searchAndReplace"],
2175 );
2176}
2177
2178#[serde_as]
2180#[skip_serializing_none]
2181#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2182#[serde(rename_all = "camelCase")]
2183#[non_exhaustive]
2184pub struct NesEditSuggestion {
2185 pub id: String,
2187 pub uri: String,
2189 pub edits: Vec<NesTextEdit>,
2191 #[serde_as(deserialize_as = "DefaultOnError")]
2193 #[schemars(extend("x-deserialize-default-on-error" = true))]
2194 #[serde(default)]
2195 pub cursor_position: Option<Position>,
2196 #[serde(rename = "_meta")]
2202 pub meta: Option<Meta>,
2203}
2204
2205impl NesEditSuggestion {
2206 #[must_use]
2207 pub fn new(id: impl Into<String>, uri: impl Into<String>, edits: Vec<NesTextEdit>) -> Self {
2208 Self {
2209 id: id.into(),
2210 uri: uri.into(),
2211 edits,
2212 cursor_position: None,
2213 meta: None,
2214 }
2215 }
2216
2217 #[must_use]
2218 pub fn cursor_position(mut self, cursor_position: impl IntoOption<Position>) -> Self {
2219 self.cursor_position = cursor_position.into_option();
2220 self
2221 }
2222
2223 #[must_use]
2229 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2230 self.meta = meta.into_option();
2231 self
2232 }
2233}
2234
2235#[skip_serializing_none]
2237#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2238#[serde(rename_all = "camelCase")]
2239#[non_exhaustive]
2240pub struct NesTextEdit {
2241 pub range: Range,
2243 pub new_text: String,
2245 #[serde(rename = "_meta")]
2251 pub meta: Option<Meta>,
2252}
2253
2254impl NesTextEdit {
2255 #[must_use]
2256 pub fn new(range: Range, new_text: impl Into<String>) -> Self {
2257 Self {
2258 range,
2259 new_text: new_text.into(),
2260 meta: None,
2261 }
2262 }
2263
2264 #[must_use]
2270 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2271 self.meta = meta.into_option();
2272 self
2273 }
2274}
2275
2276#[skip_serializing_none]
2278#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2279#[serde(rename_all = "camelCase")]
2280#[non_exhaustive]
2281pub struct NesJumpSuggestion {
2282 pub id: String,
2284 pub uri: String,
2286 pub position: Position,
2288 #[serde(rename = "_meta")]
2294 pub meta: Option<Meta>,
2295}
2296
2297impl NesJumpSuggestion {
2298 #[must_use]
2299 pub fn new(id: impl Into<String>, uri: impl Into<String>, position: Position) -> Self {
2300 Self {
2301 id: id.into(),
2302 uri: uri.into(),
2303 position,
2304 meta: None,
2305 }
2306 }
2307
2308 #[must_use]
2314 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2315 self.meta = meta.into_option();
2316 self
2317 }
2318}
2319
2320#[skip_serializing_none]
2322#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2323#[serde(rename_all = "camelCase")]
2324#[non_exhaustive]
2325pub struct NesRenameSuggestion {
2326 pub id: String,
2328 pub uri: String,
2330 pub position: Position,
2332 pub new_name: String,
2334 #[serde(rename = "_meta")]
2340 pub meta: Option<Meta>,
2341}
2342
2343impl NesRenameSuggestion {
2344 #[must_use]
2345 pub fn new(
2346 id: impl Into<String>,
2347 uri: impl Into<String>,
2348 position: Position,
2349 new_name: impl Into<String>,
2350 ) -> Self {
2351 Self {
2352 id: id.into(),
2353 uri: uri.into(),
2354 position,
2355 new_name: new_name.into(),
2356 meta: None,
2357 }
2358 }
2359
2360 #[must_use]
2366 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2367 self.meta = meta.into_option();
2368 self
2369 }
2370}
2371
2372#[skip_serializing_none]
2374#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2375#[serde(rename_all = "camelCase")]
2376#[non_exhaustive]
2377pub struct NesSearchAndReplaceSuggestion {
2378 pub id: String,
2380 pub uri: String,
2382 pub search: String,
2384 pub replace: String,
2386 pub is_regex: Option<bool>,
2388 #[serde(rename = "_meta")]
2394 pub meta: Option<Meta>,
2395}
2396
2397impl NesSearchAndReplaceSuggestion {
2398 #[must_use]
2399 pub fn new(
2400 id: impl Into<String>,
2401 uri: impl Into<String>,
2402 search: impl Into<String>,
2403 replace: impl Into<String>,
2404 ) -> Self {
2405 Self {
2406 id: id.into(),
2407 uri: uri.into(),
2408 search: search.into(),
2409 replace: replace.into(),
2410 is_regex: None,
2411 meta: None,
2412 }
2413 }
2414
2415 #[must_use]
2416 pub fn is_regex(mut self, is_regex: impl IntoOption<bool>) -> Self {
2417 self.is_regex = is_regex.into_option();
2418 self
2419 }
2420
2421 #[must_use]
2427 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2428 self.meta = meta.into_option();
2429 self
2430 }
2431}
2432
2433#[skip_serializing_none]
2437#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2438#[schemars(extend("x-side" = "agent", "x-method" = NES_ACCEPT_METHOD_NAME))]
2439#[serde(rename_all = "camelCase")]
2440#[non_exhaustive]
2441pub struct AcceptNesNotification {
2442 pub session_id: SessionId,
2444 pub id: String,
2446 #[serde(rename = "_meta")]
2452 pub meta: Option<Meta>,
2453}
2454
2455impl AcceptNesNotification {
2456 #[must_use]
2457 pub fn new(session_id: impl Into<SessionId>, id: impl Into<String>) -> Self {
2458 Self {
2459 session_id: session_id.into(),
2460 id: id.into(),
2461 meta: None,
2462 }
2463 }
2464
2465 #[must_use]
2471 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2472 self.meta = meta.into_option();
2473 self
2474 }
2475}
2476
2477#[serde_as]
2479#[skip_serializing_none]
2480#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2481#[schemars(extend("x-side" = "agent", "x-method" = NES_REJECT_METHOD_NAME))]
2482#[serde(rename_all = "camelCase")]
2483#[non_exhaustive]
2484pub struct RejectNesNotification {
2485 pub session_id: SessionId,
2487 pub id: String,
2489 #[serde_as(deserialize_as = "DefaultOnError")]
2491 #[schemars(extend("x-deserialize-default-on-error" = true))]
2492 #[serde(default)]
2493 pub reason: Option<NesRejectReason>,
2494 #[serde(rename = "_meta")]
2500 pub meta: Option<Meta>,
2501}
2502
2503impl RejectNesNotification {
2504 #[must_use]
2505 pub fn new(session_id: impl Into<SessionId>, id: impl Into<String>) -> Self {
2506 Self {
2507 session_id: session_id.into(),
2508 id: id.into(),
2509 reason: None,
2510 meta: None,
2511 }
2512 }
2513
2514 #[must_use]
2515 pub fn reason(mut self, reason: impl IntoOption<NesRejectReason>) -> Self {
2516 self.reason = reason.into_option();
2517 self
2518 }
2519
2520 #[must_use]
2526 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2527 self.meta = meta.into_option();
2528 self
2529 }
2530}
2531
2532#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
2534#[non_exhaustive]
2535pub enum NesRejectReason {
2536 #[serde(rename = "rejected")]
2538 Rejected,
2539 #[serde(rename = "ignored")]
2541 Ignored,
2542 #[serde(rename = "replaced")]
2544 Replaced,
2545 #[serde(rename = "cancelled")]
2547 Cancelled,
2548 #[serde(untagged)]
2554 Other(String),
2555}
2556
2557#[cfg(test)]
2558mod tests {
2559 use super::*;
2560 use serde_json::json;
2561
2562 #[test]
2563 fn test_position_encoding_kind_serialization() {
2564 assert_eq!(
2565 serde_json::to_value(&PositionEncodingKind::Utf16).unwrap(),
2566 json!("utf-16")
2567 );
2568 assert_eq!(
2569 serde_json::to_value(&PositionEncodingKind::Utf32).unwrap(),
2570 json!("utf-32")
2571 );
2572 assert_eq!(
2573 serde_json::to_value(&PositionEncodingKind::Utf8).unwrap(),
2574 json!("utf-8")
2575 );
2576
2577 assert_eq!(
2578 serde_json::from_value::<PositionEncodingKind>(json!("utf-16")).unwrap(),
2579 PositionEncodingKind::Utf16
2580 );
2581 assert_eq!(
2582 serde_json::from_value::<PositionEncodingKind>(json!("utf-32")).unwrap(),
2583 PositionEncodingKind::Utf32
2584 );
2585 assert_eq!(
2586 serde_json::from_value::<PositionEncodingKind>(json!("utf-8")).unwrap(),
2587 PositionEncodingKind::Utf8
2588 );
2589 assert!(serde_json::from_value::<PositionEncodingKind>(json!("_future")).is_err());
2590 }
2591
2592 #[test]
2593 fn test_client_capabilities_skip_unknown_position_encodings() {
2594 let caps: crate::v2::ClientCapabilities = serde_json::from_value(json!({
2595 "positionEncodings": ["_future", "utf-8", "utf-16"]
2596 }))
2597 .unwrap();
2598
2599 assert_eq!(
2600 caps.position_encodings,
2601 vec![PositionEncodingKind::Utf8, PositionEncodingKind::Utf16]
2602 );
2603 }
2604
2605 #[test]
2606 fn test_agent_nes_capabilities_serialization() {
2607 let caps = NesCapabilities::new()
2608 .events(
2609 NesEventCapabilities::new().document(
2610 NesDocumentEventCapabilities::new()
2611 .did_open(NesDocumentDidOpenCapabilities::default())
2612 .did_change(NesDocumentDidChangeCapabilities::new(
2613 TextDocumentSyncKind::Incremental,
2614 ))
2615 .did_close(NesDocumentDidCloseCapabilities::default())
2616 .did_save(NesDocumentDidSaveCapabilities::default())
2617 .did_focus(NesDocumentDidFocusCapabilities::default()),
2618 ),
2619 )
2620 .context(
2621 NesContextCapabilities::new()
2622 .recent_files(NesRecentFilesCapabilities {
2623 max_count: Some(10),
2624 meta: None,
2625 })
2626 .related_snippets(NesRelatedSnippetsCapabilities::default())
2627 .edit_history(NesEditHistoryCapabilities {
2628 max_count: Some(6),
2629 meta: None,
2630 })
2631 .user_actions(NesUserActionsCapabilities {
2632 max_count: Some(16),
2633 meta: None,
2634 })
2635 .open_files(NesOpenFilesCapabilities::default())
2636 .diagnostics(NesDiagnosticsCapabilities::default()),
2637 );
2638
2639 let json = serde_json::to_value(&caps).unwrap();
2640 assert_eq!(
2641 json,
2642 json!({
2643 "events": {
2644 "document": {
2645 "didOpen": {},
2646 "didChange": {
2647 "syncKind": "incremental"
2648 },
2649 "didClose": {},
2650 "didSave": {},
2651 "didFocus": {}
2652 }
2653 },
2654 "context": {
2655 "recentFiles": {
2656 "maxCount": 10
2657 },
2658 "relatedSnippets": {},
2659 "editHistory": {
2660 "maxCount": 6
2661 },
2662 "userActions": {
2663 "maxCount": 16
2664 },
2665 "openFiles": {},
2666 "diagnostics": {}
2667 }
2668 })
2669 );
2670
2671 let deserialized: NesCapabilities = serde_json::from_value(json).unwrap();
2673 assert_eq!(deserialized, caps);
2674 }
2675
2676 #[test]
2677 fn test_client_nes_capabilities_serialization() {
2678 let caps = ClientNesCapabilities::new()
2679 .jump(NesJumpCapabilities::default())
2680 .rename(NesRenameCapabilities::default())
2681 .search_and_replace(NesSearchAndReplaceCapabilities::default());
2682
2683 let json = serde_json::to_value(&caps).unwrap();
2684 assert_eq!(
2685 json,
2686 json!({
2687 "jump": {},
2688 "rename": {},
2689 "searchAndReplace": {}
2690 })
2691 );
2692
2693 let deserialized: ClientNesCapabilities = serde_json::from_value(json).unwrap();
2694 assert_eq!(deserialized, caps);
2695 }
2696
2697 #[test]
2698 fn test_document_did_open_serialization() {
2699 let notification = DidOpenDocumentNotification::new(
2700 "session_123",
2701 "file:///path/to/file.rs",
2702 "rust",
2703 1,
2704 "fn main() {\n println!(\"hello\");\n}\n",
2705 );
2706
2707 let json = serde_json::to_value(¬ification).unwrap();
2708 assert_eq!(
2709 json,
2710 json!({
2711 "sessionId": "session_123",
2712 "uri": "file:///path/to/file.rs",
2713 "languageId": "rust",
2714 "version": 1,
2715 "text": "fn main() {\n println!(\"hello\");\n}\n"
2716 })
2717 );
2718
2719 let deserialized: DidOpenDocumentNotification = serde_json::from_value(json).unwrap();
2720 assert_eq!(deserialized, notification);
2721 }
2722
2723 #[test]
2724 fn test_document_did_change_incremental_serialization() {
2725 let notification = DidChangeDocumentNotification::new(
2726 "session_123",
2727 "file:///path/to/file.rs",
2728 2,
2729 vec![TextDocumentContentChangeEvent::incremental(
2730 Range::new(Position::new(1, 4), Position::new(1, 4)),
2731 "let x = 42;\n ",
2732 )],
2733 );
2734
2735 let json = serde_json::to_value(¬ification).unwrap();
2736 assert_eq!(
2737 json,
2738 json!({
2739 "sessionId": "session_123",
2740 "uri": "file:///path/to/file.rs",
2741 "version": 2,
2742 "contentChanges": [
2743 {
2744 "range": {
2745 "start": { "line": 1, "character": 4 },
2746 "end": { "line": 1, "character": 4 }
2747 },
2748 "text": "let x = 42;\n "
2749 }
2750 ]
2751 })
2752 );
2753 }
2754
2755 #[test]
2756 fn test_document_did_change_full_serialization() {
2757 let notification = DidChangeDocumentNotification::new(
2758 "session_123",
2759 "file:///path/to/file.rs",
2760 2,
2761 vec![TextDocumentContentChangeEvent::full(
2762 "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n",
2763 )],
2764 );
2765
2766 let json = serde_json::to_value(¬ification).unwrap();
2767 assert_eq!(
2768 json,
2769 json!({
2770 "sessionId": "session_123",
2771 "uri": "file:///path/to/file.rs",
2772 "version": 2,
2773 "contentChanges": [
2774 {
2775 "text": "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n"
2776 }
2777 ]
2778 })
2779 );
2780 }
2781
2782 #[test]
2783 fn test_document_did_close_serialization() {
2784 let notification =
2785 DidCloseDocumentNotification::new("session_123", "file:///path/to/file.rs");
2786 let json = serde_json::to_value(¬ification).unwrap();
2787 assert_eq!(
2788 json,
2789 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
2790 );
2791 }
2792
2793 #[test]
2794 fn test_document_did_save_serialization() {
2795 let notification =
2796 DidSaveDocumentNotification::new("session_123", "file:///path/to/file.rs");
2797 let json = serde_json::to_value(¬ification).unwrap();
2798 assert_eq!(
2799 json,
2800 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
2801 );
2802 }
2803
2804 #[test]
2805 fn test_document_did_focus_serialization() {
2806 let notification = DidFocusDocumentNotification::new(
2807 "session_123",
2808 "file:///path/to/file.rs",
2809 2,
2810 Position::new(5, 12),
2811 Range::new(Position::new(0, 0), Position::new(45, 0)),
2812 );
2813
2814 let json = serde_json::to_value(¬ification).unwrap();
2815 assert_eq!(
2816 json,
2817 json!({
2818 "sessionId": "session_123",
2819 "uri": "file:///path/to/file.rs",
2820 "version": 2,
2821 "position": { "line": 5, "character": 12 },
2822 "visibleRange": {
2823 "start": { "line": 0, "character": 0 },
2824 "end": { "line": 45, "character": 0 }
2825 }
2826 })
2827 );
2828 }
2829
2830 #[test]
2831 fn test_nes_suggestion_edit_serialization() {
2832 let suggestion = NesSuggestion::Edit(
2833 NesEditSuggestion::new(
2834 "sugg_001",
2835 "file:///path/to/other_file.rs",
2836 vec![NesTextEdit::new(
2837 Range::new(Position::new(5, 0), Position::new(5, 10)),
2838 "let result = helper();",
2839 )],
2840 )
2841 .cursor_position(Position::new(5, 22)),
2842 );
2843
2844 let json = serde_json::to_value(&suggestion).unwrap();
2845 assert_eq!(
2846 json,
2847 json!({
2848 "kind": "edit",
2849 "id": "sugg_001",
2850 "uri": "file:///path/to/other_file.rs",
2851 "edits": [
2852 {
2853 "range": {
2854 "start": { "line": 5, "character": 0 },
2855 "end": { "line": 5, "character": 10 }
2856 },
2857 "newText": "let result = helper();"
2858 }
2859 ],
2860 "cursorPosition": { "line": 5, "character": 22 }
2861 })
2862 );
2863
2864 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
2865 assert_eq!(deserialized, suggestion);
2866 }
2867
2868 #[test]
2869 fn test_nes_suggestion_unknown_variant() {
2870 let suggestion: NesSuggestion = serde_json::from_value(json!({
2871 "kind": "_preview",
2872 "id": "sugg_001",
2873 "label": "Preview generated file"
2874 }))
2875 .unwrap();
2876
2877 let NesSuggestion::Other(unknown) = suggestion else {
2878 panic!("expected unknown NES suggestion");
2879 };
2880
2881 assert_eq!(unknown.kind, "_preview");
2882 assert_eq!(unknown.fields.get("id"), Some(&json!("sugg_001")));
2883 assert_eq!(
2884 serde_json::to_value(NesSuggestion::Other(unknown)).unwrap(),
2885 json!({
2886 "kind": "_preview",
2887 "id": "sugg_001",
2888 "label": "Preview generated file"
2889 })
2890 );
2891 }
2892
2893 #[test]
2894 fn test_nes_suggestion_unknown_does_not_hide_malformed_known_variant() {
2895 assert!(
2896 serde_json::from_value::<NesSuggestion>(json!({
2897 "kind": "edit"
2898 }))
2899 .is_err()
2900 );
2901 }
2902
2903 #[test]
2904 fn test_nes_suggestion_jump_serialization() {
2905 let suggestion = NesSuggestion::Jump(NesJumpSuggestion::new(
2906 "sugg_002",
2907 "file:///path/to/other_file.rs",
2908 Position::new(15, 4),
2909 ));
2910
2911 let json = serde_json::to_value(&suggestion).unwrap();
2912 assert_eq!(
2913 json,
2914 json!({
2915 "kind": "jump",
2916 "id": "sugg_002",
2917 "uri": "file:///path/to/other_file.rs",
2918 "position": { "line": 15, "character": 4 }
2919 })
2920 );
2921
2922 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
2923 assert_eq!(deserialized, suggestion);
2924 }
2925
2926 #[test]
2927 fn test_nes_suggestion_rename_serialization() {
2928 let suggestion = NesSuggestion::Rename(NesRenameSuggestion::new(
2929 "sugg_003",
2930 "file:///path/to/file.rs",
2931 Position::new(5, 10),
2932 "calculateTotal",
2933 ));
2934
2935 let json = serde_json::to_value(&suggestion).unwrap();
2936 assert_eq!(
2937 json,
2938 json!({
2939 "kind": "rename",
2940 "id": "sugg_003",
2941 "uri": "file:///path/to/file.rs",
2942 "position": { "line": 5, "character": 10 },
2943 "newName": "calculateTotal"
2944 })
2945 );
2946
2947 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
2948 assert_eq!(deserialized, suggestion);
2949 }
2950
2951 #[test]
2952 fn test_nes_suggestion_search_and_replace_serialization() {
2953 let suggestion = NesSuggestion::SearchAndReplace(
2954 NesSearchAndReplaceSuggestion::new(
2955 "sugg_004",
2956 "file:///path/to/file.rs",
2957 "oldFunction",
2958 "newFunction",
2959 )
2960 .is_regex(false),
2961 );
2962
2963 let json = serde_json::to_value(&suggestion).unwrap();
2964 assert_eq!(
2965 json,
2966 json!({
2967 "kind": "searchAndReplace",
2968 "id": "sugg_004",
2969 "uri": "file:///path/to/file.rs",
2970 "search": "oldFunction",
2971 "replace": "newFunction",
2972 "isRegex": false
2973 })
2974 );
2975
2976 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
2977 assert_eq!(deserialized, suggestion);
2978 }
2979
2980 #[test]
2981 fn test_nes_start_request_serialization() {
2982 let request = StartNesRequest::new()
2983 .workspace_uri("file:///Users/alice/projects/my-app")
2984 .workspace_folders(vec![WorkspaceFolder::new(
2985 "file:///Users/alice/projects/my-app",
2986 "my-app",
2987 )])
2988 .repository(NesRepository::new(
2989 "my-app",
2990 "alice",
2991 "https://github.com/alice/my-app.git",
2992 ));
2993
2994 let json = serde_json::to_value(&request).unwrap();
2995 assert_eq!(
2996 json,
2997 json!({
2998 "workspaceUri": "file:///Users/alice/projects/my-app",
2999 "workspaceFolders": [
3000 {
3001 "uri": "file:///Users/alice/projects/my-app",
3002 "name": "my-app"
3003 }
3004 ],
3005 "repository": {
3006 "name": "my-app",
3007 "owner": "alice",
3008 "remoteUrl": "https://github.com/alice/my-app.git"
3009 }
3010 })
3011 );
3012 }
3013
3014 #[test]
3015 fn test_nes_start_response_serialization() {
3016 let response = StartNesResponse::new("session_abc123");
3017 let json = serde_json::to_value(&response).unwrap();
3018 assert_eq!(json, json!({ "sessionId": "session_abc123" }));
3019 }
3020
3021 #[test]
3022 fn test_nes_trigger_kind_serialization() {
3023 assert_eq!(
3024 serde_json::to_value(&NesTriggerKind::Automatic).unwrap(),
3025 json!("automatic")
3026 );
3027 assert_eq!(
3028 serde_json::to_value(&NesTriggerKind::Diagnostic).unwrap(),
3029 json!("diagnostic")
3030 );
3031 assert_eq!(
3032 serde_json::to_value(&NesTriggerKind::Manual).unwrap(),
3033 json!("manual")
3034 );
3035 }
3036
3037 #[test]
3038 fn test_nes_reject_reason_serialization() {
3039 assert_eq!(
3040 serde_json::to_value(&NesRejectReason::Rejected).unwrap(),
3041 json!("rejected")
3042 );
3043 assert_eq!(
3044 serde_json::to_value(&NesRejectReason::Ignored).unwrap(),
3045 json!("ignored")
3046 );
3047 assert_eq!(
3048 serde_json::to_value(&NesRejectReason::Replaced).unwrap(),
3049 json!("replaced")
3050 );
3051 assert_eq!(
3052 serde_json::to_value(&NesRejectReason::Cancelled).unwrap(),
3053 json!("cancelled")
3054 );
3055 }
3056
3057 #[test]
3058 fn test_nes_accept_notification_serialization() {
3059 let notification = AcceptNesNotification::new("session_123", "sugg_001");
3060 let json = serde_json::to_value(¬ification).unwrap();
3061 assert_eq!(
3062 json,
3063 json!({ "sessionId": "session_123", "id": "sugg_001" })
3064 );
3065 }
3066
3067 #[test]
3068 fn test_nes_reject_notification_serialization() {
3069 let notification =
3070 RejectNesNotification::new("session_123", "sugg_001").reason(NesRejectReason::Rejected);
3071 let json = serde_json::to_value(¬ification).unwrap();
3072 assert_eq!(
3073 json,
3074 json!({ "sessionId": "session_123", "id": "sugg_001", "reason": "rejected" })
3075 );
3076 }
3077
3078 #[test]
3079 fn test_nes_suggest_request_with_context_serialization() {
3080 let request = SuggestNesRequest::new(
3081 "session_123",
3082 "file:///path/to/file.rs",
3083 2,
3084 Position::new(5, 12),
3085 NesTriggerKind::Automatic,
3086 )
3087 .selection(Range::new(Position::new(5, 4), Position::new(5, 12)))
3088 .context(
3089 NesSuggestContext::new()
3090 .recent_files(vec![NesRecentFile::new(
3091 "file:///path/to/utils.rs",
3092 "rust",
3093 "pub fn helper() -> i32 { 42 }\n",
3094 )])
3095 .diagnostics(vec![NesDiagnostic::new(
3096 "file:///path/to/file.rs",
3097 Range::new(Position::new(5, 0), Position::new(5, 10)),
3098 NesDiagnosticSeverity::Error,
3099 "cannot find value `foo` in this scope",
3100 )]),
3101 );
3102
3103 let json = serde_json::to_value(&request).unwrap();
3104 assert_eq!(json["sessionId"], "session_123");
3105 assert_eq!(json["uri"], "file:///path/to/file.rs");
3106 assert_eq!(json["version"], 2);
3107 assert_eq!(json["triggerKind"], "automatic");
3108 assert_eq!(
3109 json["context"]["recentFiles"][0]["uri"],
3110 "file:///path/to/utils.rs"
3111 );
3112 assert_eq!(json["context"]["diagnostics"][0]["severity"], "error");
3113 }
3114
3115 #[test]
3116 fn test_text_document_sync_kind_serialization() {
3117 assert_eq!(
3118 serde_json::to_value(&TextDocumentSyncKind::Full).unwrap(),
3119 json!("full")
3120 );
3121 assert_eq!(
3122 serde_json::to_value(&TextDocumentSyncKind::Incremental).unwrap(),
3123 json!("incremental")
3124 );
3125 assert!(serde_json::from_value::<TextDocumentSyncKind>(json!("_future")).is_err());
3126 }
3127
3128 #[test]
3129 fn test_document_event_capabilities_drop_unknown_did_change_sync_kind() {
3130 let caps: NesDocumentEventCapabilities = serde_json::from_value(json!({
3131 "didChange": {
3132 "syncKind": "_future"
3133 }
3134 }))
3135 .unwrap();
3136
3137 assert_eq!(caps.did_change, None);
3138 }
3139
3140 #[test]
3141 fn test_document_did_change_capabilities_requires_sync_kind() {
3142 assert!(serde_json::from_value::<NesDocumentDidChangeCapabilities>(json!({})).is_err());
3143 }
3144
3145 #[test]
3146 fn test_nes_suggest_response_serialization() {
3147 let response = SuggestNesResponse::new(vec![
3148 NesSuggestion::Edit(NesEditSuggestion::new(
3149 "sugg_001",
3150 "file:///path/to/file.rs",
3151 vec![NesTextEdit::new(
3152 Range::new(Position::new(5, 0), Position::new(5, 10)),
3153 "let result = helper();",
3154 )],
3155 )),
3156 NesSuggestion::Jump(NesJumpSuggestion::new(
3157 "sugg_002",
3158 "file:///path/to/other.rs",
3159 Position::new(10, 0),
3160 )),
3161 ]);
3162
3163 let json = serde_json::to_value(&response).unwrap();
3164 assert_eq!(json["suggestions"].as_array().unwrap().len(), 2);
3165 assert_eq!(json["suggestions"][0]["kind"], "edit");
3166 assert_eq!(json["suggestions"][1]["kind"], "jump");
3167 }
3168}