1use std::{collections::BTreeMap, sync::Arc};
8
9use derive_more::{Display, From};
10#[cfg(feature = "schemars")]
11use schemars::Schema;
12use serde::{Deserialize, Serialize};
13use serde_with::{DefaultOnError, DefaultOnNull, serde_as, skip_serializing_none};
14
15use super::{Meta, SessionId};
16use crate::IntoOption;
17
18pub(crate) const NES_START_METHOD_NAME: &str = "nes/start";
22pub(crate) const NES_SUGGEST_METHOD_NAME: &str = "nes/suggest";
24pub(crate) const NES_ACCEPT_METHOD_NAME: &str = "nes/accept";
26pub(crate) const NES_REJECT_METHOD_NAME: &str = "nes/reject";
28
29#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
36#[serde(transparent)]
37#[from(forward)]
38#[non_exhaustive]
39pub struct NesSuggestionId(pub Arc<str>);
40
41impl NesSuggestionId {
42 #[must_use]
44 pub fn new(id: impl Into<Self>) -> Self {
45 id.into()
46 }
47}
48pub(crate) const NES_CLOSE_METHOD_NAME: &str = "nes/close";
50pub(crate) const DOCUMENT_DID_OPEN_METHOD_NAME: &str = "document/didOpen";
52pub(crate) const DOCUMENT_DID_CHANGE_METHOD_NAME: &str = "document/didChange";
54pub(crate) const DOCUMENT_DID_CLOSE_METHOD_NAME: &str = "document/didClose";
56pub(crate) const DOCUMENT_DID_SAVE_METHOD_NAME: &str = "document/didSave";
58pub(crate) const DOCUMENT_DID_FOCUS_METHOD_NAME: &str = "document/didFocus";
60
61#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
67#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
68#[non_exhaustive]
69pub enum PositionEncodingKind {
70 #[serde(rename = "utf-16")]
72 Utf16,
73 #[serde(rename = "utf-32")]
75 Utf32,
76 #[serde(rename = "utf-8")]
78 Utf8,
79}
80
81#[serde_as]
85#[skip_serializing_none]
86#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
88#[serde(rename_all = "camelCase")]
89#[non_exhaustive]
90pub struct Position {
91 pub line: u32,
93 pub character: u32,
95 #[serde_as(deserialize_as = "DefaultOnError")]
101 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
102 #[serde(default)]
103 #[serde(rename = "_meta")]
104 pub meta: Option<Meta>,
105}
106
107impl Position {
108 #[must_use]
110 pub fn new(line: u32, character: u32) -> Self {
111 Self {
112 line,
113 character,
114 meta: None,
115 }
116 }
117
118 #[must_use]
124 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
125 self.meta = meta.into_option();
126 self
127 }
128}
129
130#[serde_as]
132#[skip_serializing_none]
133#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
135#[serde(rename_all = "camelCase")]
136#[non_exhaustive]
137pub struct Range {
138 pub start: Position,
140 pub end: Position,
142 #[serde_as(deserialize_as = "DefaultOnError")]
148 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
149 #[serde(default)]
150 #[serde(rename = "_meta")]
151 pub meta: Option<Meta>,
152}
153
154impl Range {
155 #[must_use]
157 pub fn new(start: Position, end: Position) -> Self {
158 Self {
159 start,
160 end,
161 meta: None,
162 }
163 }
164
165 #[must_use]
171 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
172 self.meta = meta.into_option();
173 self
174 }
175}
176
177#[serde_as]
184#[skip_serializing_none]
185#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
186#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
187#[serde(rename_all = "camelCase")]
188#[non_exhaustive]
189pub struct NesCapabilities {
190 #[serde_as(deserialize_as = "DefaultOnError")]
192 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
193 #[serde(default)]
194 pub events: Option<NesEventCapabilities>,
195 #[serde_as(deserialize_as = "DefaultOnError")]
197 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
198 #[serde(default)]
199 pub context: Option<NesContextCapabilities>,
200 #[serde_as(deserialize_as = "DefaultOnError")]
206 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
207 #[serde(default)]
208 #[serde(rename = "_meta")]
209 pub meta: Option<Meta>,
210}
211
212impl NesCapabilities {
213 #[must_use]
215 pub fn new() -> Self {
216 Self::default()
217 }
218
219 #[must_use]
221 pub fn events(mut self, events: impl IntoOption<NesEventCapabilities>) -> Self {
222 self.events = events.into_option();
223 self
224 }
225
226 #[must_use]
228 pub fn context(mut self, context: impl IntoOption<NesContextCapabilities>) -> Self {
229 self.context = context.into_option();
230 self
231 }
232
233 #[must_use]
239 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
240 self.meta = meta.into_option();
241 self
242 }
243}
244
245#[serde_as]
247#[skip_serializing_none]
248#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
249#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
250#[serde(rename_all = "camelCase")]
251#[non_exhaustive]
252pub struct NesEventCapabilities {
253 #[serde_as(deserialize_as = "DefaultOnError")]
255 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
256 #[serde(default)]
257 pub document: Option<NesDocumentEventCapabilities>,
258 #[serde_as(deserialize_as = "DefaultOnError")]
264 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
265 #[serde(default)]
266 #[serde(rename = "_meta")]
267 pub meta: Option<Meta>,
268}
269
270impl NesEventCapabilities {
271 #[must_use]
273 pub fn new() -> Self {
274 Self::default()
275 }
276
277 #[must_use]
279 pub fn document(mut self, document: impl IntoOption<NesDocumentEventCapabilities>) -> Self {
280 self.document = document.into_option();
281 self
282 }
283
284 #[must_use]
290 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
291 self.meta = meta.into_option();
292 self
293 }
294}
295
296#[serde_as]
298#[skip_serializing_none]
299#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
300#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
301#[serde(rename_all = "camelCase")]
302#[non_exhaustive]
303pub struct NesDocumentEventCapabilities {
304 #[serde_as(deserialize_as = "DefaultOnError")]
306 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
307 #[serde(default)]
308 pub did_open: Option<NesDocumentDidOpenCapabilities>,
309 #[serde_as(deserialize_as = "DefaultOnError")]
311 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
312 #[serde(default)]
313 pub did_change: Option<NesDocumentDidChangeCapabilities>,
314 #[serde_as(deserialize_as = "DefaultOnError")]
316 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
317 #[serde(default)]
318 pub did_close: Option<NesDocumentDidCloseCapabilities>,
319 #[serde_as(deserialize_as = "DefaultOnError")]
321 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
322 #[serde(default)]
323 pub did_save: Option<NesDocumentDidSaveCapabilities>,
324 #[serde_as(deserialize_as = "DefaultOnError")]
326 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
327 #[serde(default)]
328 pub did_focus: Option<NesDocumentDidFocusCapabilities>,
329 #[serde_as(deserialize_as = "DefaultOnError")]
335 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
336 #[serde(default)]
337 #[serde(rename = "_meta")]
338 pub meta: Option<Meta>,
339}
340
341impl NesDocumentEventCapabilities {
342 #[must_use]
344 pub fn new() -> Self {
345 Self::default()
346 }
347
348 #[must_use]
350 pub fn did_open(mut self, did_open: impl IntoOption<NesDocumentDidOpenCapabilities>) -> Self {
351 self.did_open = did_open.into_option();
352 self
353 }
354
355 #[must_use]
357 pub fn did_change(
358 mut self,
359 did_change: impl IntoOption<NesDocumentDidChangeCapabilities>,
360 ) -> Self {
361 self.did_change = did_change.into_option();
362 self
363 }
364
365 #[must_use]
367 pub fn did_close(
368 mut self,
369 did_close: impl IntoOption<NesDocumentDidCloseCapabilities>,
370 ) -> Self {
371 self.did_close = did_close.into_option();
372 self
373 }
374
375 #[must_use]
377 pub fn did_save(mut self, did_save: impl IntoOption<NesDocumentDidSaveCapabilities>) -> Self {
378 self.did_save = did_save.into_option();
379 self
380 }
381
382 #[must_use]
384 pub fn did_focus(
385 mut self,
386 did_focus: impl IntoOption<NesDocumentDidFocusCapabilities>,
387 ) -> Self {
388 self.did_focus = did_focus.into_option();
389 self
390 }
391
392 #[must_use]
398 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
399 self.meta = meta.into_option();
400 self
401 }
402}
403
404#[serde_as]
406#[skip_serializing_none]
407#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
408#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
409#[serde(rename_all = "camelCase")]
410#[non_exhaustive]
411pub struct NesDocumentDidOpenCapabilities {
412 #[serde_as(deserialize_as = "DefaultOnError")]
418 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
419 #[serde(default)]
420 #[serde(rename = "_meta")]
421 pub meta: Option<Meta>,
422}
423
424impl NesDocumentDidOpenCapabilities {
425 #[must_use]
427 pub fn new() -> Self {
428 Self::default()
429 }
430}
431
432#[serde_as]
434#[skip_serializing_none]
435#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
436#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
437#[serde(rename_all = "camelCase")]
438#[non_exhaustive]
439pub struct NesDocumentDidChangeCapabilities {
440 pub sync_kind: TextDocumentSyncKind,
442 #[serde_as(deserialize_as = "DefaultOnError")]
448 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
449 #[serde(default)]
450 #[serde(rename = "_meta")]
451 pub meta: Option<Meta>,
452}
453
454impl NesDocumentDidChangeCapabilities {
455 #[must_use]
457 pub fn new(sync_kind: TextDocumentSyncKind) -> Self {
458 Self {
459 sync_kind,
460 meta: None,
461 }
462 }
463
464 #[must_use]
470 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
471 self.meta = meta.into_option();
472 self
473 }
474}
475
476#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
478#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
479#[non_exhaustive]
480pub enum TextDocumentSyncKind {
481 #[serde(rename = "full")]
483 Full,
484 #[serde(rename = "incremental")]
486 Incremental,
487}
488
489#[serde_as]
491#[skip_serializing_none]
492#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
493#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
494#[serde(rename_all = "camelCase")]
495#[non_exhaustive]
496pub struct NesDocumentDidCloseCapabilities {
497 #[serde_as(deserialize_as = "DefaultOnError")]
503 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
504 #[serde(default)]
505 #[serde(rename = "_meta")]
506 pub meta: Option<Meta>,
507}
508
509impl NesDocumentDidCloseCapabilities {
510 #[must_use]
512 pub fn new() -> Self {
513 Self::default()
514 }
515}
516
517#[serde_as]
519#[skip_serializing_none]
520#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
521#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
522#[serde(rename_all = "camelCase")]
523#[non_exhaustive]
524pub struct NesDocumentDidSaveCapabilities {
525 #[serde_as(deserialize_as = "DefaultOnError")]
531 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
532 #[serde(default)]
533 #[serde(rename = "_meta")]
534 pub meta: Option<Meta>,
535}
536
537impl NesDocumentDidSaveCapabilities {
538 #[must_use]
540 pub fn new() -> Self {
541 Self::default()
542 }
543}
544
545#[serde_as]
547#[skip_serializing_none]
548#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
549#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
550#[serde(rename_all = "camelCase")]
551#[non_exhaustive]
552pub struct NesDocumentDidFocusCapabilities {
553 #[serde_as(deserialize_as = "DefaultOnError")]
559 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
560 #[serde(default)]
561 #[serde(rename = "_meta")]
562 pub meta: Option<Meta>,
563}
564
565impl NesDocumentDidFocusCapabilities {
566 #[must_use]
568 pub fn new() -> Self {
569 Self::default()
570 }
571}
572
573#[serde_as]
575#[skip_serializing_none]
576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
577#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
578#[serde(rename_all = "camelCase")]
579#[non_exhaustive]
580pub struct NesContextCapabilities {
581 #[serde_as(deserialize_as = "DefaultOnError")]
583 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
584 #[serde(default)]
585 pub recent_files: Option<NesRecentFilesCapabilities>,
586 #[serde_as(deserialize_as = "DefaultOnError")]
588 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
589 #[serde(default)]
590 pub related_snippets: Option<NesRelatedSnippetsCapabilities>,
591 #[serde_as(deserialize_as = "DefaultOnError")]
593 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
594 #[serde(default)]
595 pub edit_history: Option<NesEditHistoryCapabilities>,
596 #[serde_as(deserialize_as = "DefaultOnError")]
598 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
599 #[serde(default)]
600 pub user_actions: Option<NesUserActionsCapabilities>,
601 #[serde_as(deserialize_as = "DefaultOnError")]
603 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
604 #[serde(default)]
605 pub open_files: Option<NesOpenFilesCapabilities>,
606 #[serde_as(deserialize_as = "DefaultOnError")]
608 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
609 #[serde(default)]
610 pub diagnostics: Option<NesDiagnosticsCapabilities>,
611 #[serde_as(deserialize_as = "DefaultOnError")]
617 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
618 #[serde(default)]
619 #[serde(rename = "_meta")]
620 pub meta: Option<Meta>,
621}
622
623impl NesContextCapabilities {
624 #[must_use]
626 pub fn new() -> Self {
627 Self::default()
628 }
629
630 #[must_use]
632 pub fn recent_files(
633 mut self,
634 recent_files: impl IntoOption<NesRecentFilesCapabilities>,
635 ) -> Self {
636 self.recent_files = recent_files.into_option();
637 self
638 }
639
640 #[must_use]
642 pub fn related_snippets(
643 mut self,
644 related_snippets: impl IntoOption<NesRelatedSnippetsCapabilities>,
645 ) -> Self {
646 self.related_snippets = related_snippets.into_option();
647 self
648 }
649
650 #[must_use]
652 pub fn edit_history(
653 mut self,
654 edit_history: impl IntoOption<NesEditHistoryCapabilities>,
655 ) -> Self {
656 self.edit_history = edit_history.into_option();
657 self
658 }
659
660 #[must_use]
662 pub fn user_actions(
663 mut self,
664 user_actions: impl IntoOption<NesUserActionsCapabilities>,
665 ) -> Self {
666 self.user_actions = user_actions.into_option();
667 self
668 }
669
670 #[must_use]
672 pub fn open_files(mut self, open_files: impl IntoOption<NesOpenFilesCapabilities>) -> Self {
673 self.open_files = open_files.into_option();
674 self
675 }
676
677 #[must_use]
679 pub fn diagnostics(mut self, diagnostics: impl IntoOption<NesDiagnosticsCapabilities>) -> Self {
680 self.diagnostics = diagnostics.into_option();
681 self
682 }
683
684 #[must_use]
690 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
691 self.meta = meta.into_option();
692 self
693 }
694}
695
696#[serde_as]
698#[skip_serializing_none]
699#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
700#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
701#[serde(rename_all = "camelCase")]
702#[non_exhaustive]
703pub struct NesRecentFilesCapabilities {
704 #[serde_as(deserialize_as = "DefaultOnError")]
706 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
707 #[serde(default)]
708 pub max_count: Option<u32>,
709 #[serde_as(deserialize_as = "DefaultOnError")]
715 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
716 #[serde(default)]
717 #[serde(rename = "_meta")]
718 pub meta: Option<Meta>,
719}
720
721impl NesRecentFilesCapabilities {
722 #[must_use]
724 pub fn new() -> Self {
725 Self::default()
726 }
727}
728
729#[serde_as]
731#[skip_serializing_none]
732#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
733#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
734#[serde(rename_all = "camelCase")]
735#[non_exhaustive]
736pub struct NesRelatedSnippetsCapabilities {
737 #[serde_as(deserialize_as = "DefaultOnError")]
743 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
744 #[serde(default)]
745 #[serde(rename = "_meta")]
746 pub meta: Option<Meta>,
747}
748
749impl NesRelatedSnippetsCapabilities {
750 #[must_use]
752 pub fn new() -> Self {
753 Self::default()
754 }
755}
756
757#[serde_as]
759#[skip_serializing_none]
760#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
761#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
762#[serde(rename_all = "camelCase")]
763#[non_exhaustive]
764pub struct NesEditHistoryCapabilities {
765 #[serde_as(deserialize_as = "DefaultOnError")]
767 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
768 #[serde(default)]
769 pub max_count: Option<u32>,
770 #[serde_as(deserialize_as = "DefaultOnError")]
776 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
777 #[serde(default)]
778 #[serde(rename = "_meta")]
779 pub meta: Option<Meta>,
780}
781
782impl NesEditHistoryCapabilities {
783 #[must_use]
785 pub fn new() -> Self {
786 Self::default()
787 }
788}
789
790#[serde_as]
792#[skip_serializing_none]
793#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
794#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
795#[serde(rename_all = "camelCase")]
796#[non_exhaustive]
797pub struct NesUserActionsCapabilities {
798 #[serde_as(deserialize_as = "DefaultOnError")]
800 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
801 #[serde(default)]
802 pub max_count: Option<u32>,
803 #[serde_as(deserialize_as = "DefaultOnError")]
809 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
810 #[serde(default)]
811 #[serde(rename = "_meta")]
812 pub meta: Option<Meta>,
813}
814
815impl NesUserActionsCapabilities {
816 #[must_use]
818 pub fn new() -> Self {
819 Self::default()
820 }
821}
822
823#[serde_as]
825#[skip_serializing_none]
826#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
827#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
828#[serde(rename_all = "camelCase")]
829#[non_exhaustive]
830pub struct NesOpenFilesCapabilities {
831 #[serde_as(deserialize_as = "DefaultOnError")]
837 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
838 #[serde(default)]
839 #[serde(rename = "_meta")]
840 pub meta: Option<Meta>,
841}
842
843impl NesOpenFilesCapabilities {
844 #[must_use]
846 pub fn new() -> Self {
847 Self::default()
848 }
849}
850
851#[serde_as]
853#[skip_serializing_none]
854#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
855#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
856#[serde(rename_all = "camelCase")]
857#[non_exhaustive]
858pub struct NesDiagnosticsCapabilities {
859 #[serde_as(deserialize_as = "DefaultOnError")]
865 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
866 #[serde(default)]
867 #[serde(rename = "_meta")]
868 pub meta: Option<Meta>,
869}
870
871impl NesDiagnosticsCapabilities {
872 #[must_use]
874 pub fn new() -> Self {
875 Self::default()
876 }
877}
878
879#[serde_as]
883#[skip_serializing_none]
884#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
885#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
886#[serde(rename_all = "camelCase")]
887#[non_exhaustive]
888pub struct ClientNesCapabilities {
889 #[serde_as(deserialize_as = "DefaultOnError")]
891 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
892 #[serde(default)]
893 pub jump: Option<NesJumpCapabilities>,
894 #[serde_as(deserialize_as = "DefaultOnError")]
896 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
897 #[serde(default)]
898 pub rename: Option<NesRenameCapabilities>,
899 #[serde_as(deserialize_as = "DefaultOnError")]
901 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
902 #[serde(default)]
903 pub search_and_replace: Option<NesSearchAndReplaceCapabilities>,
904 #[serde_as(deserialize_as = "DefaultOnError")]
910 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
911 #[serde(default)]
912 #[serde(rename = "_meta")]
913 pub meta: Option<Meta>,
914}
915
916impl ClientNesCapabilities {
917 #[must_use]
919 pub fn new() -> Self {
920 Self::default()
921 }
922
923 #[must_use]
925 pub fn jump(mut self, jump: impl IntoOption<NesJumpCapabilities>) -> Self {
926 self.jump = jump.into_option();
927 self
928 }
929
930 #[must_use]
932 pub fn rename(mut self, rename: impl IntoOption<NesRenameCapabilities>) -> Self {
933 self.rename = rename.into_option();
934 self
935 }
936
937 #[must_use]
939 pub fn search_and_replace(
940 mut self,
941 search_and_replace: impl IntoOption<NesSearchAndReplaceCapabilities>,
942 ) -> Self {
943 self.search_and_replace = search_and_replace.into_option();
944 self
945 }
946
947 #[must_use]
953 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
954 self.meta = meta.into_option();
955 self
956 }
957}
958
959#[serde_as]
961#[skip_serializing_none]
962#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
963#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
964#[serde(rename_all = "camelCase")]
965#[non_exhaustive]
966pub struct NesJumpCapabilities {
967 #[serde_as(deserialize_as = "DefaultOnError")]
973 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
974 #[serde(default)]
975 #[serde(rename = "_meta")]
976 pub meta: Option<Meta>,
977}
978
979impl NesJumpCapabilities {
980 #[must_use]
982 pub fn new() -> Self {
983 Self::default()
984 }
985}
986
987#[serde_as]
989#[skip_serializing_none]
990#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
991#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
992#[serde(rename_all = "camelCase")]
993#[non_exhaustive]
994pub struct NesRenameCapabilities {
995 #[serde_as(deserialize_as = "DefaultOnError")]
1001 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1002 #[serde(default)]
1003 #[serde(rename = "_meta")]
1004 pub meta: Option<Meta>,
1005}
1006
1007impl NesRenameCapabilities {
1008 #[must_use]
1010 pub fn new() -> Self {
1011 Self::default()
1012 }
1013}
1014
1015#[serde_as]
1017#[skip_serializing_none]
1018#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1019#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1020#[serde(rename_all = "camelCase")]
1021#[non_exhaustive]
1022pub struct NesSearchAndReplaceCapabilities {
1023 #[serde_as(deserialize_as = "DefaultOnError")]
1029 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1030 #[serde(default)]
1031 #[serde(rename = "_meta")]
1032 pub meta: Option<Meta>,
1033}
1034
1035impl NesSearchAndReplaceCapabilities {
1036 #[must_use]
1038 pub fn new() -> Self {
1039 Self::default()
1040 }
1041}
1042
1043#[serde_as]
1047#[skip_serializing_none]
1048#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1049#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1050#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_OPEN_METHOD_NAME)))]
1051#[serde(rename_all = "camelCase")]
1052#[non_exhaustive]
1053pub struct DidOpenDocumentNotification {
1054 pub session_id: SessionId,
1056 #[cfg_attr(feature = "schemars", schemars(url))]
1058 pub uri: String,
1059 pub language_id: String,
1061 pub version: i64,
1063 pub text: String,
1065 #[serde_as(deserialize_as = "DefaultOnError")]
1071 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1072 #[serde(default)]
1073 #[serde(rename = "_meta")]
1074 pub meta: Option<Meta>,
1075}
1076
1077impl DidOpenDocumentNotification {
1078 #[must_use]
1080 pub fn new(
1081 session_id: impl Into<SessionId>,
1082 uri: impl Into<String>,
1083 language_id: impl Into<String>,
1084 version: i64,
1085 text: impl Into<String>,
1086 ) -> Self {
1087 Self {
1088 session_id: session_id.into(),
1089 uri: uri.into(),
1090 language_id: language_id.into(),
1091 version,
1092 text: text.into(),
1093 meta: None,
1094 }
1095 }
1096
1097 #[must_use]
1103 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1104 self.meta = meta.into_option();
1105 self
1106 }
1107}
1108
1109#[serde_as]
1111#[skip_serializing_none]
1112#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1114#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CHANGE_METHOD_NAME)))]
1115#[serde(rename_all = "camelCase")]
1116#[non_exhaustive]
1117pub struct DidChangeDocumentNotification {
1118 pub session_id: SessionId,
1120 #[cfg_attr(feature = "schemars", schemars(url))]
1122 pub uri: String,
1123 pub version: i64,
1125 #[serde_as(deserialize_as = "DefaultOnNull")]
1127 pub content_changes: Vec<TextDocumentContentChangeEvent>,
1128 #[serde_as(deserialize_as = "DefaultOnError")]
1134 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1135 #[serde(default)]
1136 #[serde(rename = "_meta")]
1137 pub meta: Option<Meta>,
1138}
1139
1140impl DidChangeDocumentNotification {
1141 #[must_use]
1143 pub fn new(
1144 session_id: impl Into<SessionId>,
1145 uri: impl Into<String>,
1146 version: i64,
1147 content_changes: Vec<TextDocumentContentChangeEvent>,
1148 ) -> Self {
1149 Self {
1150 session_id: session_id.into(),
1151 uri: uri.into(),
1152 version,
1153 content_changes,
1154 meta: None,
1155 }
1156 }
1157
1158 #[must_use]
1164 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1165 self.meta = meta.into_option();
1166 self
1167 }
1168}
1169
1170#[serde_as]
1175#[skip_serializing_none]
1176#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1177#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1178#[serde(rename_all = "camelCase")]
1179#[non_exhaustive]
1180pub struct TextDocumentContentChangeEvent {
1181 #[serde(default)]
1183 pub range: Option<Range>,
1184 pub text: String,
1186 #[serde_as(deserialize_as = "DefaultOnError")]
1192 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1193 #[serde(default)]
1194 #[serde(rename = "_meta")]
1195 pub meta: Option<Meta>,
1196}
1197
1198impl TextDocumentContentChangeEvent {
1199 #[must_use]
1201 pub fn full(text: impl Into<String>) -> Self {
1202 Self {
1203 range: None,
1204 text: text.into(),
1205 meta: None,
1206 }
1207 }
1208
1209 #[must_use]
1211 pub fn incremental(range: Range, text: impl Into<String>) -> Self {
1212 Self {
1213 range: Some(range),
1214 text: text.into(),
1215 meta: None,
1216 }
1217 }
1218
1219 #[must_use]
1225 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1226 self.meta = meta.into_option();
1227 self
1228 }
1229}
1230
1231#[serde_as]
1233#[skip_serializing_none]
1234#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1235#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1236#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CLOSE_METHOD_NAME)))]
1237#[serde(rename_all = "camelCase")]
1238#[non_exhaustive]
1239pub struct DidCloseDocumentNotification {
1240 pub session_id: SessionId,
1242 #[cfg_attr(feature = "schemars", schemars(url))]
1244 pub uri: String,
1245 #[serde_as(deserialize_as = "DefaultOnError")]
1251 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1252 #[serde(default)]
1253 #[serde(rename = "_meta")]
1254 pub meta: Option<Meta>,
1255}
1256
1257impl DidCloseDocumentNotification {
1258 #[must_use]
1260 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1261 Self {
1262 session_id: session_id.into(),
1263 uri: uri.into(),
1264 meta: None,
1265 }
1266 }
1267
1268 #[must_use]
1274 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1275 self.meta = meta.into_option();
1276 self
1277 }
1278}
1279
1280#[serde_as]
1282#[skip_serializing_none]
1283#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1284#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1285#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_SAVE_METHOD_NAME)))]
1286#[serde(rename_all = "camelCase")]
1287#[non_exhaustive]
1288pub struct DidSaveDocumentNotification {
1289 pub session_id: SessionId,
1291 #[cfg_attr(feature = "schemars", schemars(url))]
1293 pub uri: String,
1294 #[serde_as(deserialize_as = "DefaultOnError")]
1300 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1301 #[serde(default)]
1302 #[serde(rename = "_meta")]
1303 pub meta: Option<Meta>,
1304}
1305
1306impl DidSaveDocumentNotification {
1307 #[must_use]
1309 pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1310 Self {
1311 session_id: session_id.into(),
1312 uri: uri.into(),
1313 meta: None,
1314 }
1315 }
1316
1317 #[must_use]
1323 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1324 self.meta = meta.into_option();
1325 self
1326 }
1327}
1328
1329#[serde_as]
1331#[skip_serializing_none]
1332#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1333#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1334#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_FOCUS_METHOD_NAME)))]
1335#[serde(rename_all = "camelCase")]
1336#[non_exhaustive]
1337pub struct DidFocusDocumentNotification {
1338 pub session_id: SessionId,
1340 #[cfg_attr(feature = "schemars", schemars(url))]
1342 pub uri: String,
1343 pub version: i64,
1345 pub position: Position,
1347 pub visible_range: Range,
1349 #[serde_as(deserialize_as = "DefaultOnError")]
1355 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1356 #[serde(default)]
1357 #[serde(rename = "_meta")]
1358 pub meta: Option<Meta>,
1359}
1360
1361impl DidFocusDocumentNotification {
1362 #[must_use]
1364 pub fn new(
1365 session_id: impl Into<SessionId>,
1366 uri: impl Into<String>,
1367 version: i64,
1368 position: Position,
1369 visible_range: Range,
1370 ) -> Self {
1371 Self {
1372 session_id: session_id.into(),
1373 uri: uri.into(),
1374 version,
1375 position,
1376 visible_range,
1377 meta: None,
1378 }
1379 }
1380
1381 #[must_use]
1387 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1388 self.meta = meta.into_option();
1389 self
1390 }
1391}
1392
1393crate::serde_util::default_on_null! {
1396 #[serde_as]
1398 #[skip_serializing_none]
1399 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1400 #[derive(Debug, Clone, Serialize, PartialEq, Eq)]
1401 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1402 #[serde(rename_all = "camelCase")]
1403 #[non_exhaustive]
1404 pub struct StartNesRequest {
1405 #[serde_as(deserialize_as = "DefaultOnError")]
1407 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1408 #[cfg_attr(feature = "schemars", schemars(url))]
1409 #[serde(default)]
1410 pub workspace_uri: Option<String>,
1411 #[serde(default)]
1413 pub workspace_folders: Option<Vec<WorkspaceFolder>>,
1414 #[serde_as(deserialize_as = "DefaultOnError")]
1416 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1417 #[serde(default)]
1418 pub repository: Option<NesRepository>,
1419 #[serde_as(deserialize_as = "DefaultOnError")]
1425 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1426 #[serde(default)]
1427 #[serde(rename = "_meta")]
1428 pub meta: Option<Meta>,
1429 }
1430}
1431
1432impl StartNesRequest {
1433 #[must_use]
1435 pub fn new() -> Self {
1436 Self {
1437 workspace_uri: None,
1438 workspace_folders: None,
1439 repository: None,
1440 meta: None,
1441 }
1442 }
1443
1444 #[must_use]
1446 pub fn workspace_uri(mut self, workspace_uri: impl IntoOption<String>) -> Self {
1447 self.workspace_uri = workspace_uri.into_option();
1448 self
1449 }
1450
1451 #[must_use]
1453 pub fn workspace_folders(
1454 mut self,
1455 workspace_folders: impl IntoOption<Vec<WorkspaceFolder>>,
1456 ) -> Self {
1457 self.workspace_folders = workspace_folders.into_option();
1458 self
1459 }
1460
1461 #[must_use]
1463 pub fn repository(mut self, repository: impl IntoOption<NesRepository>) -> Self {
1464 self.repository = repository.into_option();
1465 self
1466 }
1467
1468 #[must_use]
1474 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1475 self.meta = meta.into_option();
1476 self
1477 }
1478}
1479
1480impl Default for StartNesRequest {
1481 fn default() -> Self {
1482 Self::new()
1483 }
1484}
1485
1486#[serde_as]
1488#[skip_serializing_none]
1489#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1490#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1491#[serde(rename_all = "camelCase")]
1492#[non_exhaustive]
1493pub struct WorkspaceFolder {
1494 #[cfg_attr(feature = "schemars", schemars(url))]
1496 pub uri: String,
1497 pub name: String,
1499 #[serde_as(deserialize_as = "DefaultOnError")]
1505 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1506 #[serde(default)]
1507 #[serde(rename = "_meta")]
1508 pub meta: Option<Meta>,
1509}
1510
1511impl WorkspaceFolder {
1512 #[must_use]
1514 pub fn new(uri: impl Into<String>, name: impl Into<String>) -> Self {
1515 Self {
1516 uri: uri.into(),
1517 name: name.into(),
1518 meta: None,
1519 }
1520 }
1521
1522 #[must_use]
1528 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1529 self.meta = meta.into_option();
1530 self
1531 }
1532}
1533
1534#[serde_as]
1536#[skip_serializing_none]
1537#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1538#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1539#[serde(rename_all = "camelCase")]
1540#[non_exhaustive]
1541pub struct NesRepository {
1542 pub name: String,
1544 pub owner: String,
1546 pub remote_url: String,
1548 #[serde_as(deserialize_as = "DefaultOnError")]
1554 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1555 #[serde(default)]
1556 #[serde(rename = "_meta")]
1557 pub meta: Option<Meta>,
1558}
1559
1560impl NesRepository {
1561 #[must_use]
1563 pub fn new(
1564 name: impl Into<String>,
1565 owner: impl Into<String>,
1566 remote_url: impl Into<String>,
1567 ) -> Self {
1568 Self {
1569 name: name.into(),
1570 owner: owner.into(),
1571 remote_url: remote_url.into(),
1572 meta: None,
1573 }
1574 }
1575
1576 #[must_use]
1582 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1583 self.meta = meta.into_option();
1584 self
1585 }
1586}
1587
1588#[serde_as]
1590#[skip_serializing_none]
1591#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1592#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1593#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1594#[serde(rename_all = "camelCase")]
1595#[non_exhaustive]
1596pub struct StartNesResponse {
1597 pub session_id: SessionId,
1599 #[serde_as(deserialize_as = "DefaultOnError")]
1605 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1606 #[serde(default)]
1607 #[serde(rename = "_meta")]
1608 pub meta: Option<Meta>,
1609}
1610
1611impl StartNesResponse {
1612 #[must_use]
1614 pub fn new(session_id: impl Into<SessionId>) -> Self {
1615 Self {
1616 session_id: session_id.into(),
1617 meta: None,
1618 }
1619 }
1620
1621 #[must_use]
1627 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1628 self.meta = meta.into_option();
1629 self
1630 }
1631}
1632
1633#[serde_as]
1640#[skip_serializing_none]
1641#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1642#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1643#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1644#[serde(rename_all = "camelCase")]
1645#[non_exhaustive]
1646pub struct CloseNesRequest {
1647 pub session_id: SessionId,
1649 #[serde_as(deserialize_as = "DefaultOnError")]
1655 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1656 #[serde(default)]
1657 #[serde(rename = "_meta")]
1658 pub meta: Option<Meta>,
1659}
1660
1661impl CloseNesRequest {
1662 #[must_use]
1664 pub fn new(session_id: impl Into<SessionId>) -> Self {
1665 Self {
1666 session_id: session_id.into(),
1667 meta: None,
1668 }
1669 }
1670
1671 #[must_use]
1677 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1678 self.meta = meta.into_option();
1679 self
1680 }
1681}
1682
1683crate::serde_util::default_on_null! {
1684 #[serde_as]
1686 #[skip_serializing_none]
1687 #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1688 #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1689 #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1690 #[serde(rename_all = "camelCase")]
1691 #[non_exhaustive]
1692 pub struct CloseNesResponse {
1693 #[serde_as(deserialize_as = "DefaultOnError")]
1699 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1700 #[serde(default)]
1701 #[serde(rename = "_meta")]
1702 pub meta: Option<Meta>,
1703 }
1704}
1705
1706impl CloseNesResponse {
1707 #[must_use]
1709 pub fn new() -> Self {
1710 Self::default()
1711 }
1712
1713 #[must_use]
1719 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1720 self.meta = meta.into_option();
1721 self
1722 }
1723}
1724
1725#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1729#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1730#[non_exhaustive]
1731pub enum NesTriggerKind {
1732 #[serde(rename = "automatic")]
1734 Automatic,
1735 #[serde(rename = "diagnostic")]
1737 Diagnostic,
1738 #[serde(rename = "manual")]
1740 Manual,
1741 #[serde(untagged)]
1747 Other(String),
1748}
1749
1750#[serde_as]
1752#[skip_serializing_none]
1753#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1754#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1755#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
1756#[serde(rename_all = "camelCase")]
1757#[non_exhaustive]
1758pub struct SuggestNesRequest {
1759 pub session_id: SessionId,
1761 #[cfg_attr(feature = "schemars", schemars(url))]
1763 pub uri: String,
1764 pub version: i64,
1766 pub position: Position,
1768 #[serde(default)]
1770 pub selection: Option<Range>,
1771 pub trigger_kind: NesTriggerKind,
1773 #[serde(default)]
1775 pub context: Option<NesSuggestContext>,
1776 #[serde_as(deserialize_as = "DefaultOnError")]
1782 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1783 #[serde(default)]
1784 #[serde(rename = "_meta")]
1785 pub meta: Option<Meta>,
1786}
1787
1788impl SuggestNesRequest {
1789 #[must_use]
1791 pub fn new(
1792 session_id: impl Into<SessionId>,
1793 uri: impl Into<String>,
1794 version: i64,
1795 position: Position,
1796 trigger_kind: NesTriggerKind,
1797 ) -> Self {
1798 Self {
1799 session_id: session_id.into(),
1800 uri: uri.into(),
1801 version,
1802 position,
1803 selection: None,
1804 trigger_kind,
1805 context: None,
1806 meta: None,
1807 }
1808 }
1809
1810 #[must_use]
1812 pub fn selection(mut self, selection: impl IntoOption<Range>) -> Self {
1813 self.selection = selection.into_option();
1814 self
1815 }
1816
1817 #[must_use]
1819 pub fn context(mut self, context: impl IntoOption<NesSuggestContext>) -> Self {
1820 self.context = context.into_option();
1821 self
1822 }
1823
1824 #[must_use]
1830 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1831 self.meta = meta.into_option();
1832 self
1833 }
1834}
1835
1836#[serde_as]
1838#[skip_serializing_none]
1839#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1840#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1841#[serde(rename_all = "camelCase")]
1842#[non_exhaustive]
1843pub struct NesSuggestContext {
1844 #[serde(default)]
1846 pub recent_files: Option<Vec<NesRecentFile>>,
1847 #[serde(default)]
1849 pub related_snippets: Option<Vec<NesRelatedSnippet>>,
1850 #[serde(default)]
1852 pub edit_history: Option<Vec<NesEditHistoryEntry>>,
1853 #[serde(default)]
1855 pub user_actions: Option<Vec<NesUserAction>>,
1856 #[serde(default)]
1858 pub open_files: Option<Vec<NesOpenFile>>,
1859 #[serde(default)]
1861 pub diagnostics: Option<Vec<NesDiagnostic>>,
1862 #[serde_as(deserialize_as = "DefaultOnError")]
1868 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1869 #[serde(default)]
1870 #[serde(rename = "_meta")]
1871 pub meta: Option<Meta>,
1872}
1873
1874impl NesSuggestContext {
1875 #[must_use]
1877 pub fn new() -> Self {
1878 Self::default()
1879 }
1880
1881 #[must_use]
1883 pub fn recent_files(mut self, recent_files: impl IntoOption<Vec<NesRecentFile>>) -> Self {
1884 self.recent_files = recent_files.into_option();
1885 self
1886 }
1887
1888 #[must_use]
1890 pub fn related_snippets(
1891 mut self,
1892 related_snippets: impl IntoOption<Vec<NesRelatedSnippet>>,
1893 ) -> Self {
1894 self.related_snippets = related_snippets.into_option();
1895 self
1896 }
1897
1898 #[must_use]
1900 pub fn edit_history(mut self, edit_history: impl IntoOption<Vec<NesEditHistoryEntry>>) -> Self {
1901 self.edit_history = edit_history.into_option();
1902 self
1903 }
1904
1905 #[must_use]
1907 pub fn user_actions(mut self, user_actions: impl IntoOption<Vec<NesUserAction>>) -> Self {
1908 self.user_actions = user_actions.into_option();
1909 self
1910 }
1911
1912 #[must_use]
1914 pub fn open_files(mut self, open_files: impl IntoOption<Vec<NesOpenFile>>) -> Self {
1915 self.open_files = open_files.into_option();
1916 self
1917 }
1918
1919 #[must_use]
1921 pub fn diagnostics(mut self, diagnostics: impl IntoOption<Vec<NesDiagnostic>>) -> Self {
1922 self.diagnostics = diagnostics.into_option();
1923 self
1924 }
1925
1926 #[must_use]
1932 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1933 self.meta = meta.into_option();
1934 self
1935 }
1936}
1937
1938#[serde_as]
1940#[skip_serializing_none]
1941#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1942#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1943#[serde(rename_all = "camelCase")]
1944#[non_exhaustive]
1945pub struct NesRecentFile {
1946 #[cfg_attr(feature = "schemars", schemars(url))]
1948 pub uri: String,
1949 pub language_id: String,
1951 pub text: String,
1953 #[serde_as(deserialize_as = "DefaultOnError")]
1959 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1960 #[serde(default)]
1961 #[serde(rename = "_meta")]
1962 pub meta: Option<Meta>,
1963}
1964
1965impl NesRecentFile {
1966 #[must_use]
1968 pub fn new(
1969 uri: impl Into<String>,
1970 language_id: impl Into<String>,
1971 text: impl Into<String>,
1972 ) -> Self {
1973 Self {
1974 uri: uri.into(),
1975 language_id: language_id.into(),
1976 text: text.into(),
1977 meta: None,
1978 }
1979 }
1980
1981 #[must_use]
1987 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1988 self.meta = meta.into_option();
1989 self
1990 }
1991}
1992
1993#[serde_as]
1995#[skip_serializing_none]
1996#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1997#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1998#[serde(rename_all = "camelCase")]
1999#[non_exhaustive]
2000pub struct NesRelatedSnippet {
2001 #[cfg_attr(feature = "schemars", schemars(url))]
2003 pub uri: String,
2004 pub excerpts: Vec<NesExcerpt>,
2006 #[serde_as(deserialize_as = "DefaultOnError")]
2012 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2013 #[serde(default)]
2014 #[serde(rename = "_meta")]
2015 pub meta: Option<Meta>,
2016}
2017
2018impl NesRelatedSnippet {
2019 #[must_use]
2021 pub fn new(uri: impl Into<String>, excerpts: Vec<NesExcerpt>) -> Self {
2022 Self {
2023 uri: uri.into(),
2024 excerpts,
2025 meta: None,
2026 }
2027 }
2028
2029 #[must_use]
2035 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2036 self.meta = meta.into_option();
2037 self
2038 }
2039}
2040
2041#[serde_as]
2043#[skip_serializing_none]
2044#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2045#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2046#[serde(rename_all = "camelCase")]
2047#[non_exhaustive]
2048pub struct NesExcerpt {
2049 pub start_line: u32,
2051 pub end_line: u32,
2053 pub text: String,
2055 #[serde_as(deserialize_as = "DefaultOnError")]
2061 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2062 #[serde(default)]
2063 #[serde(rename = "_meta")]
2064 pub meta: Option<Meta>,
2065}
2066
2067impl NesExcerpt {
2068 #[must_use]
2070 pub fn new(start_line: u32, end_line: u32, text: impl Into<String>) -> Self {
2071 Self {
2072 start_line,
2073 end_line,
2074 text: text.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#[serde_as]
2093#[skip_serializing_none]
2094#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2095#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2096#[serde(rename_all = "camelCase")]
2097#[non_exhaustive]
2098pub struct NesEditHistoryEntry {
2099 #[cfg_attr(feature = "schemars", schemars(url))]
2101 pub uri: String,
2102 pub diff: String,
2104 #[serde_as(deserialize_as = "DefaultOnError")]
2110 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2111 #[serde(default)]
2112 #[serde(rename = "_meta")]
2113 pub meta: Option<Meta>,
2114}
2115
2116impl NesEditHistoryEntry {
2117 #[must_use]
2119 pub fn new(uri: impl Into<String>, diff: impl Into<String>) -> Self {
2120 Self {
2121 uri: uri.into(),
2122 diff: diff.into(),
2123 meta: None,
2124 }
2125 }
2126
2127 #[must_use]
2133 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2134 self.meta = meta.into_option();
2135 self
2136 }
2137}
2138
2139#[serde_as]
2141#[skip_serializing_none]
2142#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2143#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2144#[serde(rename_all = "camelCase")]
2145#[non_exhaustive]
2146pub struct NesUserAction {
2147 pub action: String,
2149 #[cfg_attr(feature = "schemars", schemars(url))]
2151 pub uri: String,
2152 pub position: Position,
2154 pub timestamp_ms: u64,
2156 #[serde_as(deserialize_as = "DefaultOnError")]
2162 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2163 #[serde(default)]
2164 #[serde(rename = "_meta")]
2165 pub meta: Option<Meta>,
2166}
2167
2168impl NesUserAction {
2169 #[must_use]
2171 pub fn new(
2172 action: impl Into<String>,
2173 uri: impl Into<String>,
2174 position: Position,
2175 timestamp_ms: u64,
2176 ) -> Self {
2177 Self {
2178 action: action.into(),
2179 uri: uri.into(),
2180 position,
2181 timestamp_ms,
2182 meta: None,
2183 }
2184 }
2185
2186 #[must_use]
2192 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2193 self.meta = meta.into_option();
2194 self
2195 }
2196}
2197
2198#[serde_as]
2200#[skip_serializing_none]
2201#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2202#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2203#[serde(rename_all = "camelCase")]
2204#[non_exhaustive]
2205pub struct NesOpenFile {
2206 #[cfg_attr(feature = "schemars", schemars(url))]
2208 pub uri: String,
2209 pub language_id: String,
2211 #[serde_as(deserialize_as = "DefaultOnError")]
2213 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2214 #[serde(default)]
2215 pub visible_range: Option<Range>,
2216 #[serde_as(deserialize_as = "DefaultOnError")]
2218 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2219 #[serde(default)]
2220 pub last_focused_ms: Option<u64>,
2221 #[serde_as(deserialize_as = "DefaultOnError")]
2227 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2228 #[serde(default)]
2229 #[serde(rename = "_meta")]
2230 pub meta: Option<Meta>,
2231}
2232
2233impl NesOpenFile {
2234 #[must_use]
2236 pub fn new(uri: impl Into<String>, language_id: impl Into<String>) -> Self {
2237 Self {
2238 uri: uri.into(),
2239 language_id: language_id.into(),
2240 visible_range: None,
2241 last_focused_ms: None,
2242 meta: None,
2243 }
2244 }
2245
2246 #[must_use]
2248 pub fn visible_range(mut self, visible_range: impl IntoOption<Range>) -> Self {
2249 self.visible_range = visible_range.into_option();
2250 self
2251 }
2252
2253 #[must_use]
2255 pub fn last_focused_ms(mut self, last_focused_ms: impl IntoOption<u64>) -> Self {
2256 self.last_focused_ms = last_focused_ms.into_option();
2257 self
2258 }
2259
2260 #[must_use]
2266 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2267 self.meta = meta.into_option();
2268 self
2269 }
2270}
2271
2272#[serde_as]
2274#[skip_serializing_none]
2275#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2276#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2277#[serde(rename_all = "camelCase")]
2278#[non_exhaustive]
2279pub struct NesDiagnostic {
2280 #[cfg_attr(feature = "schemars", schemars(url))]
2282 pub uri: String,
2283 pub range: Range,
2285 pub severity: NesDiagnosticSeverity,
2287 pub message: String,
2289 #[serde_as(deserialize_as = "DefaultOnError")]
2295 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2296 #[serde(default)]
2297 #[serde(rename = "_meta")]
2298 pub meta: Option<Meta>,
2299}
2300
2301impl NesDiagnostic {
2302 #[must_use]
2304 pub fn new(
2305 uri: impl Into<String>,
2306 range: Range,
2307 severity: NesDiagnosticSeverity,
2308 message: impl Into<String>,
2309 ) -> Self {
2310 Self {
2311 uri: uri.into(),
2312 range,
2313 severity,
2314 message: message.into(),
2315 meta: None,
2316 }
2317 }
2318
2319 #[must_use]
2325 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2326 self.meta = meta.into_option();
2327 self
2328 }
2329}
2330
2331#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2333#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2334#[non_exhaustive]
2335pub enum NesDiagnosticSeverity {
2336 #[serde(rename = "error")]
2338 Error,
2339 #[serde(rename = "warning")]
2341 Warning,
2342 #[serde(rename = "information")]
2344 Information,
2345 #[serde(rename = "hint")]
2347 Hint,
2348 #[serde(untagged)]
2354 Other(String),
2355}
2356
2357#[serde_as]
2361#[skip_serializing_none]
2362#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2363#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2364#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
2365#[serde(rename_all = "camelCase")]
2366#[non_exhaustive]
2367pub struct SuggestNesResponse {
2368 pub suggestions: Vec<NesSuggestion>,
2370 #[serde_as(deserialize_as = "DefaultOnError")]
2376 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2377 #[serde(default)]
2378 #[serde(rename = "_meta")]
2379 pub meta: Option<Meta>,
2380}
2381
2382impl SuggestNesResponse {
2383 #[must_use]
2385 pub fn new(suggestions: Vec<NesSuggestion>) -> Self {
2386 Self {
2387 suggestions,
2388 meta: None,
2389 }
2390 }
2391
2392 #[must_use]
2398 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2399 self.meta = meta.into_option();
2400 self
2401 }
2402}
2403
2404#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2406#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2407#[serde(tag = "kind", rename_all = "camelCase")]
2408#[non_exhaustive]
2409pub enum NesSuggestion {
2410 Edit(NesEditSuggestion),
2412 Jump(NesJumpSuggestion),
2414 Rename(NesRenameSuggestion),
2416 SearchAndReplace(NesSearchAndReplaceSuggestion),
2418 #[serde(untagged)]
2428 Other(OtherNesSuggestion),
2429}
2430
2431#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2433#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
2434#[cfg_attr(feature = "schemars", schemars(inline))]
2435#[cfg_attr(feature = "schemars", schemars(transform = other_nes_suggestion_schema))]
2436#[serde(rename_all = "camelCase")]
2437#[non_exhaustive]
2438pub struct OtherNesSuggestion {
2439 pub kind: String,
2445 pub suggestion_id: NesSuggestionId,
2447 #[serde(flatten)]
2449 pub fields: BTreeMap<String, serde_json::Value>,
2450}
2451
2452impl OtherNesSuggestion {
2453 #[must_use]
2455 pub fn new(
2456 kind: impl Into<String>,
2457 suggestion_id: impl Into<NesSuggestionId>,
2458 mut fields: BTreeMap<String, serde_json::Value>,
2459 ) -> Self {
2460 fields.remove("kind");
2461 fields.remove("suggestionId");
2462 Self {
2463 kind: kind.into(),
2464 suggestion_id: suggestion_id.into(),
2465 fields,
2466 }
2467 }
2468}
2469
2470impl<'de> Deserialize<'de> for OtherNesSuggestion {
2471 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2472 where
2473 D: serde::Deserializer<'de>,
2474 {
2475 let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2476 let kind = fields
2477 .remove("kind")
2478 .ok_or_else(|| serde::de::Error::missing_field("kind"))?;
2479 let serde_json::Value::String(kind) = kind else {
2480 return Err(serde::de::Error::custom("`kind` must be a string"));
2481 };
2482 let suggestion_id = fields
2483 .remove("suggestionId")
2484 .ok_or_else(|| serde::de::Error::missing_field("suggestionId"))?;
2485 let serde_json::Value::String(suggestion_id) = suggestion_id else {
2486 return Err(serde::de::Error::custom("`suggestionId` must be a string"));
2487 };
2488
2489 if is_known_nes_suggestion_kind(&kind) {
2490 return Err(serde::de::Error::custom(format!(
2491 "known NES suggestion `{kind}` did not match its schema"
2492 )));
2493 }
2494
2495 Ok(Self {
2496 kind,
2497 suggestion_id: NesSuggestionId::new(suggestion_id),
2498 fields,
2499 })
2500 }
2501}
2502
2503fn is_known_nes_suggestion_kind(kind: &str) -> bool {
2504 matches!(kind, "edit" | "jump" | "rename" | "searchAndReplace")
2505}
2506
2507#[cfg(feature = "schemars")]
2508fn other_nes_suggestion_schema(schema: &mut Schema) {
2509 super::schema_util::reject_known_string_discriminators(
2510 schema,
2511 "kind",
2512 &["edit", "jump", "rename", "searchAndReplace"],
2513 );
2514}
2515
2516#[serde_as]
2518#[skip_serializing_none]
2519#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2520#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2521#[serde(rename_all = "camelCase")]
2522#[non_exhaustive]
2523pub struct NesEditSuggestion {
2524 pub suggestion_id: NesSuggestionId,
2526 #[cfg_attr(feature = "schemars", schemars(url))]
2528 pub uri: String,
2529 #[cfg_attr(feature = "schemars", schemars(length(min = 1)))]
2531 pub edits: Vec<NesTextEdit>,
2532 #[serde_as(deserialize_as = "DefaultOnError")]
2534 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2535 #[serde(default)]
2536 pub cursor_position: Option<Position>,
2537 #[serde_as(deserialize_as = "DefaultOnError")]
2543 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2544 #[serde(default)]
2545 #[serde(rename = "_meta")]
2546 pub meta: Option<Meta>,
2547}
2548
2549impl NesEditSuggestion {
2550 #[must_use]
2552 pub fn new(
2553 suggestion_id: impl Into<NesSuggestionId>,
2554 uri: impl Into<String>,
2555 edits: Vec<NesTextEdit>,
2556 ) -> Self {
2557 Self {
2558 suggestion_id: suggestion_id.into(),
2559 uri: uri.into(),
2560 edits,
2561 cursor_position: None,
2562 meta: None,
2563 }
2564 }
2565
2566 #[must_use]
2568 pub fn cursor_position(mut self, cursor_position: impl IntoOption<Position>) -> Self {
2569 self.cursor_position = cursor_position.into_option();
2570 self
2571 }
2572
2573 #[must_use]
2579 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2580 self.meta = meta.into_option();
2581 self
2582 }
2583}
2584
2585#[serde_as]
2587#[skip_serializing_none]
2588#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2589#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2590#[serde(rename_all = "camelCase")]
2591#[non_exhaustive]
2592pub struct NesTextEdit {
2593 pub range: Range,
2595 pub new_text: String,
2597 #[serde_as(deserialize_as = "DefaultOnError")]
2603 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2604 #[serde(default)]
2605 #[serde(rename = "_meta")]
2606 pub meta: Option<Meta>,
2607}
2608
2609impl NesTextEdit {
2610 #[must_use]
2612 pub fn new(range: Range, new_text: impl Into<String>) -> Self {
2613 Self {
2614 range,
2615 new_text: new_text.into(),
2616 meta: None,
2617 }
2618 }
2619
2620 #[must_use]
2626 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2627 self.meta = meta.into_option();
2628 self
2629 }
2630}
2631
2632#[serde_as]
2634#[skip_serializing_none]
2635#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2636#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2637#[serde(rename_all = "camelCase")]
2638#[non_exhaustive]
2639pub struct NesJumpSuggestion {
2640 pub suggestion_id: NesSuggestionId,
2642 #[cfg_attr(feature = "schemars", schemars(url))]
2644 pub uri: String,
2645 pub position: Position,
2647 #[serde_as(deserialize_as = "DefaultOnError")]
2653 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2654 #[serde(default)]
2655 #[serde(rename = "_meta")]
2656 pub meta: Option<Meta>,
2657}
2658
2659impl NesJumpSuggestion {
2660 #[must_use]
2662 pub fn new(
2663 suggestion_id: impl Into<NesSuggestionId>,
2664 uri: impl Into<String>,
2665 position: Position,
2666 ) -> Self {
2667 Self {
2668 suggestion_id: suggestion_id.into(),
2669 uri: uri.into(),
2670 position,
2671 meta: None,
2672 }
2673 }
2674
2675 #[must_use]
2681 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2682 self.meta = meta.into_option();
2683 self
2684 }
2685}
2686
2687#[serde_as]
2689#[skip_serializing_none]
2690#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2691#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2692#[serde(rename_all = "camelCase")]
2693#[non_exhaustive]
2694pub struct NesRenameSuggestion {
2695 pub suggestion_id: NesSuggestionId,
2697 #[cfg_attr(feature = "schemars", schemars(url))]
2699 pub uri: String,
2700 pub position: Position,
2702 pub new_name: String,
2704 #[serde_as(deserialize_as = "DefaultOnError")]
2710 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2711 #[serde(default)]
2712 #[serde(rename = "_meta")]
2713 pub meta: Option<Meta>,
2714}
2715
2716impl NesRenameSuggestion {
2717 #[must_use]
2719 pub fn new(
2720 suggestion_id: impl Into<NesSuggestionId>,
2721 uri: impl Into<String>,
2722 position: Position,
2723 new_name: impl Into<String>,
2724 ) -> Self {
2725 Self {
2726 suggestion_id: suggestion_id.into(),
2727 uri: uri.into(),
2728 position,
2729 new_name: new_name.into(),
2730 meta: None,
2731 }
2732 }
2733
2734 #[must_use]
2740 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2741 self.meta = meta.into_option();
2742 self
2743 }
2744}
2745
2746#[serde_as]
2748#[skip_serializing_none]
2749#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2750#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2751#[serde(rename_all = "camelCase")]
2752#[non_exhaustive]
2753pub struct NesSearchAndReplaceSuggestion {
2754 pub suggestion_id: NesSuggestionId,
2756 #[cfg_attr(feature = "schemars", schemars(url))]
2758 pub uri: String,
2759 pub search: String,
2761 pub replace: String,
2763 #[serde(default)]
2765 pub is_regex: Option<bool>,
2766 #[serde_as(deserialize_as = "DefaultOnError")]
2772 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2773 #[serde(default)]
2774 #[serde(rename = "_meta")]
2775 pub meta: Option<Meta>,
2776}
2777
2778impl NesSearchAndReplaceSuggestion {
2779 #[must_use]
2781 pub fn new(
2782 suggestion_id: impl Into<NesSuggestionId>,
2783 uri: impl Into<String>,
2784 search: impl Into<String>,
2785 replace: impl Into<String>,
2786 ) -> Self {
2787 Self {
2788 suggestion_id: suggestion_id.into(),
2789 uri: uri.into(),
2790 search: search.into(),
2791 replace: replace.into(),
2792 is_regex: None,
2793 meta: None,
2794 }
2795 }
2796
2797 #[must_use]
2799 pub fn is_regex(mut self, is_regex: impl IntoOption<bool>) -> Self {
2800 self.is_regex = is_regex.into_option();
2801 self
2802 }
2803
2804 #[must_use]
2810 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2811 self.meta = meta.into_option();
2812 self
2813 }
2814}
2815
2816#[serde_as]
2820#[skip_serializing_none]
2821#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2822#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2823#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_ACCEPT_METHOD_NAME)))]
2824#[serde(rename_all = "camelCase")]
2825#[non_exhaustive]
2826pub struct AcceptNesNotification {
2827 pub session_id: SessionId,
2829 pub suggestion_id: NesSuggestionId,
2831 #[serde_as(deserialize_as = "DefaultOnError")]
2837 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2838 #[serde(default)]
2839 #[serde(rename = "_meta")]
2840 pub meta: Option<Meta>,
2841}
2842
2843impl AcceptNesNotification {
2844 #[must_use]
2846 pub fn new(
2847 session_id: impl Into<SessionId>,
2848 suggestion_id: impl Into<NesSuggestionId>,
2849 ) -> Self {
2850 Self {
2851 session_id: session_id.into(),
2852 suggestion_id: suggestion_id.into(),
2853 meta: None,
2854 }
2855 }
2856
2857 #[must_use]
2863 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2864 self.meta = meta.into_option();
2865 self
2866 }
2867}
2868
2869#[serde_as]
2871#[skip_serializing_none]
2872#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2873#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2874#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_REJECT_METHOD_NAME)))]
2875#[serde(rename_all = "camelCase")]
2876#[non_exhaustive]
2877pub struct RejectNesNotification {
2878 pub session_id: SessionId,
2880 pub suggestion_id: NesSuggestionId,
2882 #[serde_as(deserialize_as = "DefaultOnError")]
2884 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2885 #[serde(default)]
2886 pub reason: Option<NesRejectReason>,
2887 #[serde_as(deserialize_as = "DefaultOnError")]
2893 #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2894 #[serde(default)]
2895 #[serde(rename = "_meta")]
2896 pub meta: Option<Meta>,
2897}
2898
2899impl RejectNesNotification {
2900 #[must_use]
2902 pub fn new(
2903 session_id: impl Into<SessionId>,
2904 suggestion_id: impl Into<NesSuggestionId>,
2905 ) -> Self {
2906 Self {
2907 session_id: session_id.into(),
2908 suggestion_id: suggestion_id.into(),
2909 reason: None,
2910 meta: None,
2911 }
2912 }
2913
2914 #[must_use]
2916 pub fn reason(mut self, reason: impl IntoOption<NesRejectReason>) -> Self {
2917 self.reason = reason.into_option();
2918 self
2919 }
2920
2921 #[must_use]
2927 pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2928 self.meta = meta.into_option();
2929 self
2930 }
2931}
2932
2933#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2935#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2936#[non_exhaustive]
2937pub enum NesRejectReason {
2938 #[serde(rename = "rejected")]
2940 Rejected,
2941 #[serde(rename = "ignored")]
2943 Ignored,
2944 #[serde(rename = "replaced")]
2946 Replaced,
2947 #[serde(rename = "cancelled")]
2949 Cancelled,
2950 #[serde(untagged)]
2956 Other(String),
2957}
2958
2959#[cfg(test)]
2960mod tests {
2961 use super::*;
2962 use serde_json::json;
2963
2964 #[test]
2965 fn test_position_encoding_kind_serialization() {
2966 assert_eq!(
2967 serde_json::to_value(&PositionEncodingKind::Utf16).unwrap(),
2968 json!("utf-16")
2969 );
2970 assert_eq!(
2971 serde_json::to_value(&PositionEncodingKind::Utf32).unwrap(),
2972 json!("utf-32")
2973 );
2974 assert_eq!(
2975 serde_json::to_value(&PositionEncodingKind::Utf8).unwrap(),
2976 json!("utf-8")
2977 );
2978
2979 assert_eq!(
2980 serde_json::from_value::<PositionEncodingKind>(json!("utf-16")).unwrap(),
2981 PositionEncodingKind::Utf16
2982 );
2983 assert_eq!(
2984 serde_json::from_value::<PositionEncodingKind>(json!("utf-32")).unwrap(),
2985 PositionEncodingKind::Utf32
2986 );
2987 assert_eq!(
2988 serde_json::from_value::<PositionEncodingKind>(json!("utf-8")).unwrap(),
2989 PositionEncodingKind::Utf8
2990 );
2991 assert!(serde_json::from_value::<PositionEncodingKind>(json!("_future")).is_err());
2992 }
2993
2994 #[test]
2995 fn test_client_capabilities_skip_unknown_position_encodings() {
2996 let caps: crate::v2::ClientCapabilities = serde_json::from_value(json!({
2997 "positionEncodings": ["_future", "utf-8", "utf-16"]
2998 }))
2999 .unwrap();
3000
3001 assert_eq!(
3002 caps.position_encodings,
3003 vec![PositionEncodingKind::Utf8, PositionEncodingKind::Utf16]
3004 );
3005 }
3006
3007 #[test]
3008 fn test_agent_nes_capabilities_serialization() {
3009 let caps = NesCapabilities::new()
3010 .events(
3011 NesEventCapabilities::new().document(
3012 NesDocumentEventCapabilities::new()
3013 .did_open(NesDocumentDidOpenCapabilities::default())
3014 .did_change(NesDocumentDidChangeCapabilities::new(
3015 TextDocumentSyncKind::Incremental,
3016 ))
3017 .did_close(NesDocumentDidCloseCapabilities::default())
3018 .did_save(NesDocumentDidSaveCapabilities::default())
3019 .did_focus(NesDocumentDidFocusCapabilities::default()),
3020 ),
3021 )
3022 .context(
3023 NesContextCapabilities::new()
3024 .recent_files(NesRecentFilesCapabilities {
3025 max_count: Some(10),
3026 meta: None,
3027 })
3028 .related_snippets(NesRelatedSnippetsCapabilities::default())
3029 .edit_history(NesEditHistoryCapabilities {
3030 max_count: Some(6),
3031 meta: None,
3032 })
3033 .user_actions(NesUserActionsCapabilities {
3034 max_count: Some(16),
3035 meta: None,
3036 })
3037 .open_files(NesOpenFilesCapabilities::default())
3038 .diagnostics(NesDiagnosticsCapabilities::default()),
3039 );
3040
3041 let json = serde_json::to_value(&caps).unwrap();
3042 assert_eq!(
3043 json,
3044 json!({
3045 "events": {
3046 "document": {
3047 "didOpen": {},
3048 "didChange": {
3049 "syncKind": "incremental"
3050 },
3051 "didClose": {},
3052 "didSave": {},
3053 "didFocus": {}
3054 }
3055 },
3056 "context": {
3057 "recentFiles": {
3058 "maxCount": 10
3059 },
3060 "relatedSnippets": {},
3061 "editHistory": {
3062 "maxCount": 6
3063 },
3064 "userActions": {
3065 "maxCount": 16
3066 },
3067 "openFiles": {},
3068 "diagnostics": {}
3069 }
3070 })
3071 );
3072
3073 let deserialized: NesCapabilities = serde_json::from_value(json).unwrap();
3075 assert_eq!(deserialized, caps);
3076 }
3077
3078 #[test]
3079 fn test_client_nes_capabilities_serialization() {
3080 let caps = ClientNesCapabilities::new()
3081 .jump(NesJumpCapabilities::default())
3082 .rename(NesRenameCapabilities::default())
3083 .search_and_replace(NesSearchAndReplaceCapabilities::default());
3084
3085 let json = serde_json::to_value(&caps).unwrap();
3086 assert_eq!(
3087 json,
3088 json!({
3089 "jump": {},
3090 "rename": {},
3091 "searchAndReplace": {}
3092 })
3093 );
3094
3095 let deserialized: ClientNesCapabilities = serde_json::from_value(json).unwrap();
3096 assert_eq!(deserialized, caps);
3097 }
3098
3099 #[test]
3100 fn test_document_did_open_serialization() {
3101 let notification = DidOpenDocumentNotification::new(
3102 "session_123",
3103 "file:///path/to/file.rs",
3104 "rust",
3105 1,
3106 "fn main() {\n println!(\"hello\");\n}\n",
3107 );
3108
3109 let json = serde_json::to_value(¬ification).unwrap();
3110 assert_eq!(
3111 json,
3112 json!({
3113 "sessionId": "session_123",
3114 "uri": "file:///path/to/file.rs",
3115 "languageId": "rust",
3116 "version": 1,
3117 "text": "fn main() {\n println!(\"hello\");\n}\n"
3118 })
3119 );
3120
3121 let deserialized: DidOpenDocumentNotification = serde_json::from_value(json).unwrap();
3122 assert_eq!(deserialized, notification);
3123 }
3124
3125 #[test]
3126 fn test_document_did_change_incremental_serialization() {
3127 let notification = DidChangeDocumentNotification::new(
3128 "session_123",
3129 "file:///path/to/file.rs",
3130 2,
3131 vec![TextDocumentContentChangeEvent::incremental(
3132 Range::new(Position::new(1, 4), Position::new(1, 4)),
3133 "let x = 42;\n ",
3134 )],
3135 );
3136
3137 let json = serde_json::to_value(¬ification).unwrap();
3138 assert_eq!(
3139 json,
3140 json!({
3141 "sessionId": "session_123",
3142 "uri": "file:///path/to/file.rs",
3143 "version": 2,
3144 "contentChanges": [
3145 {
3146 "range": {
3147 "start": { "line": 1, "character": 4 },
3148 "end": { "line": 1, "character": 4 }
3149 },
3150 "text": "let x = 42;\n "
3151 }
3152 ]
3153 })
3154 );
3155 }
3156
3157 #[test]
3158 fn test_document_did_change_full_serialization() {
3159 let notification = DidChangeDocumentNotification::new(
3160 "session_123",
3161 "file:///path/to/file.rs",
3162 2,
3163 vec![TextDocumentContentChangeEvent::full(
3164 "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n",
3165 )],
3166 );
3167
3168 let json = serde_json::to_value(¬ification).unwrap();
3169 assert_eq!(
3170 json,
3171 json!({
3172 "sessionId": "session_123",
3173 "uri": "file:///path/to/file.rs",
3174 "version": 2,
3175 "contentChanges": [
3176 {
3177 "text": "fn main() {\n let x = 42;\n println!(\"hello\");\n}\n"
3178 }
3179 ]
3180 })
3181 );
3182 }
3183
3184 #[test]
3185 fn test_document_did_close_serialization() {
3186 let notification =
3187 DidCloseDocumentNotification::new("session_123", "file:///path/to/file.rs");
3188 let json = serde_json::to_value(¬ification).unwrap();
3189 assert_eq!(
3190 json,
3191 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3192 );
3193 }
3194
3195 #[test]
3196 fn test_document_did_save_serialization() {
3197 let notification =
3198 DidSaveDocumentNotification::new("session_123", "file:///path/to/file.rs");
3199 let json = serde_json::to_value(¬ification).unwrap();
3200 assert_eq!(
3201 json,
3202 json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3203 );
3204 }
3205
3206 #[test]
3207 fn test_document_did_focus_serialization() {
3208 let notification = DidFocusDocumentNotification::new(
3209 "session_123",
3210 "file:///path/to/file.rs",
3211 2,
3212 Position::new(5, 12),
3213 Range::new(Position::new(0, 0), Position::new(45, 0)),
3214 );
3215
3216 let json = serde_json::to_value(¬ification).unwrap();
3217 assert_eq!(
3218 json,
3219 json!({
3220 "sessionId": "session_123",
3221 "uri": "file:///path/to/file.rs",
3222 "version": 2,
3223 "position": { "line": 5, "character": 12 },
3224 "visibleRange": {
3225 "start": { "line": 0, "character": 0 },
3226 "end": { "line": 45, "character": 0 }
3227 }
3228 })
3229 );
3230 }
3231
3232 #[test]
3233 fn test_nes_suggestion_edit_serialization() {
3234 let suggestion = NesSuggestion::Edit(
3235 NesEditSuggestion::new(
3236 "sugg_001",
3237 "file:///path/to/other_file.rs",
3238 vec![NesTextEdit::new(
3239 Range::new(Position::new(5, 0), Position::new(5, 10)),
3240 "let result = helper();",
3241 )],
3242 )
3243 .cursor_position(Position::new(5, 22)),
3244 );
3245
3246 let json = serde_json::to_value(&suggestion).unwrap();
3247 assert_eq!(
3248 json,
3249 json!({
3250 "kind": "edit",
3251 "suggestionId": "sugg_001",
3252 "uri": "file:///path/to/other_file.rs",
3253 "edits": [
3254 {
3255 "range": {
3256 "start": { "line": 5, "character": 0 },
3257 "end": { "line": 5, "character": 10 }
3258 },
3259 "newText": "let result = helper();"
3260 }
3261 ],
3262 "cursorPosition": { "line": 5, "character": 22 }
3263 })
3264 );
3265
3266 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3267 assert_eq!(deserialized, suggestion);
3268 }
3269
3270 #[test]
3271 fn test_nes_suggestion_unknown_variant() {
3272 let suggestion: NesSuggestion = serde_json::from_value(json!({
3273 "kind": "_preview",
3274 "suggestionId": "sugg_001",
3275 "label": "Preview generated file"
3276 }))
3277 .unwrap();
3278
3279 let NesSuggestion::Other(unknown) = suggestion else {
3280 panic!("expected unknown NES suggestion");
3281 };
3282
3283 assert_eq!(unknown.kind, "_preview");
3284 assert_eq!(unknown.suggestion_id.to_string(), "sugg_001");
3285 assert!(!unknown.fields.contains_key("suggestionId"));
3286 assert_eq!(
3287 serde_json::to_value(NesSuggestion::Other(unknown)).unwrap(),
3288 json!({
3289 "kind": "_preview",
3290 "suggestionId": "sugg_001",
3291 "label": "Preview generated file"
3292 })
3293 );
3294 }
3295
3296 #[test]
3297 fn test_nes_suggestion_unknown_does_not_hide_malformed_known_variant() {
3298 assert!(
3299 serde_json::from_value::<NesSuggestion>(json!({
3300 "kind": "edit"
3301 }))
3302 .is_err()
3303 );
3304 }
3305
3306 #[test]
3307 fn test_nes_suggestion_jump_serialization() {
3308 let suggestion = NesSuggestion::Jump(NesJumpSuggestion::new(
3309 "sugg_002",
3310 "file:///path/to/other_file.rs",
3311 Position::new(15, 4),
3312 ));
3313
3314 let json = serde_json::to_value(&suggestion).unwrap();
3315 assert_eq!(
3316 json,
3317 json!({
3318 "kind": "jump",
3319 "suggestionId": "sugg_002",
3320 "uri": "file:///path/to/other_file.rs",
3321 "position": { "line": 15, "character": 4 }
3322 })
3323 );
3324
3325 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3326 assert_eq!(deserialized, suggestion);
3327 }
3328
3329 #[test]
3330 fn test_nes_suggestion_rename_serialization() {
3331 let suggestion = NesSuggestion::Rename(NesRenameSuggestion::new(
3332 "sugg_003",
3333 "file:///path/to/file.rs",
3334 Position::new(5, 10),
3335 "calculateTotal",
3336 ));
3337
3338 let json = serde_json::to_value(&suggestion).unwrap();
3339 assert_eq!(
3340 json,
3341 json!({
3342 "kind": "rename",
3343 "suggestionId": "sugg_003",
3344 "uri": "file:///path/to/file.rs",
3345 "position": { "line": 5, "character": 10 },
3346 "newName": "calculateTotal"
3347 })
3348 );
3349
3350 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3351 assert_eq!(deserialized, suggestion);
3352 }
3353
3354 #[test]
3355 fn test_nes_suggestion_search_and_replace_serialization() {
3356 let suggestion = NesSuggestion::SearchAndReplace(
3357 NesSearchAndReplaceSuggestion::new(
3358 "sugg_004",
3359 "file:///path/to/file.rs",
3360 "oldFunction",
3361 "newFunction",
3362 )
3363 .is_regex(false),
3364 );
3365
3366 let json = serde_json::to_value(&suggestion).unwrap();
3367 assert_eq!(
3368 json,
3369 json!({
3370 "kind": "searchAndReplace",
3371 "suggestionId": "sugg_004",
3372 "uri": "file:///path/to/file.rs",
3373 "search": "oldFunction",
3374 "replace": "newFunction",
3375 "isRegex": false
3376 })
3377 );
3378
3379 let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3380 assert_eq!(deserialized, suggestion);
3381 }
3382
3383 #[test]
3384 fn test_nes_start_request_serialization() {
3385 let request = StartNesRequest::new()
3386 .workspace_uri("file:///Users/alice/projects/my-app")
3387 .workspace_folders(vec![WorkspaceFolder::new(
3388 "file:///Users/alice/projects/my-app",
3389 "my-app",
3390 )])
3391 .repository(NesRepository::new(
3392 "my-app",
3393 "alice",
3394 "https://github.com/alice/my-app.git",
3395 ));
3396
3397 let json = serde_json::to_value(&request).unwrap();
3398 assert_eq!(
3399 json,
3400 json!({
3401 "workspaceUri": "file:///Users/alice/projects/my-app",
3402 "workspaceFolders": [
3403 {
3404 "uri": "file:///Users/alice/projects/my-app",
3405 "name": "my-app"
3406 }
3407 ],
3408 "repository": {
3409 "name": "my-app",
3410 "owner": "alice",
3411 "remoteUrl": "https://github.com/alice/my-app.git"
3412 }
3413 })
3414 );
3415 }
3416
3417 #[test]
3418 fn test_nes_start_response_serialization() {
3419 let response = StartNesResponse::new("session_abc123");
3420 let json = serde_json::to_value(&response).unwrap();
3421 assert_eq!(json, json!({ "sessionId": "session_abc123" }));
3422 }
3423
3424 #[test]
3425 fn test_nes_trigger_kind_serialization() {
3426 assert_eq!(
3427 serde_json::to_value(&NesTriggerKind::Automatic).unwrap(),
3428 json!("automatic")
3429 );
3430 assert_eq!(
3431 serde_json::to_value(&NesTriggerKind::Diagnostic).unwrap(),
3432 json!("diagnostic")
3433 );
3434 assert_eq!(
3435 serde_json::to_value(&NesTriggerKind::Manual).unwrap(),
3436 json!("manual")
3437 );
3438 }
3439
3440 #[test]
3441 fn test_nes_reject_reason_serialization() {
3442 assert_eq!(
3443 serde_json::to_value(&NesRejectReason::Rejected).unwrap(),
3444 json!("rejected")
3445 );
3446 assert_eq!(
3447 serde_json::to_value(&NesRejectReason::Ignored).unwrap(),
3448 json!("ignored")
3449 );
3450 assert_eq!(
3451 serde_json::to_value(&NesRejectReason::Replaced).unwrap(),
3452 json!("replaced")
3453 );
3454 assert_eq!(
3455 serde_json::to_value(&NesRejectReason::Cancelled).unwrap(),
3456 json!("cancelled")
3457 );
3458 }
3459
3460 #[test]
3461 fn test_nes_accept_notification_serialization() {
3462 let notification = AcceptNesNotification::new("session_123", "sugg_001");
3463 let json = serde_json::to_value(¬ification).unwrap();
3464 assert_eq!(
3465 json,
3466 json!({ "sessionId": "session_123", "suggestionId": "sugg_001" })
3467 );
3468 }
3469
3470 #[test]
3471 fn test_nes_reject_notification_serialization() {
3472 let notification =
3473 RejectNesNotification::new("session_123", "sugg_001").reason(NesRejectReason::Rejected);
3474 let json = serde_json::to_value(¬ification).unwrap();
3475 assert_eq!(
3476 json,
3477 json!({ "sessionId": "session_123", "suggestionId": "sugg_001", "reason": "rejected" })
3478 );
3479 }
3480
3481 #[test]
3482 fn test_nes_suggest_request_with_context_serialization() {
3483 let request = SuggestNesRequest::new(
3484 "session_123",
3485 "file:///path/to/file.rs",
3486 2,
3487 Position::new(5, 12),
3488 NesTriggerKind::Automatic,
3489 )
3490 .selection(Range::new(Position::new(5, 4), Position::new(5, 12)))
3491 .context(
3492 NesSuggestContext::new()
3493 .recent_files(vec![NesRecentFile::new(
3494 "file:///path/to/utils.rs",
3495 "rust",
3496 "pub fn helper() -> i32 { 42 }\n",
3497 )])
3498 .diagnostics(vec![NesDiagnostic::new(
3499 "file:///path/to/file.rs",
3500 Range::new(Position::new(5, 0), Position::new(5, 10)),
3501 NesDiagnosticSeverity::Error,
3502 "cannot find value `foo` in this scope",
3503 )]),
3504 );
3505
3506 let json = serde_json::to_value(&request).unwrap();
3507 assert_eq!(json["sessionId"], "session_123");
3508 assert_eq!(json["uri"], "file:///path/to/file.rs");
3509 assert_eq!(json["version"], 2);
3510 assert_eq!(json["triggerKind"], "automatic");
3511 assert_eq!(
3512 json["context"]["recentFiles"][0]["uri"],
3513 "file:///path/to/utils.rs"
3514 );
3515 assert_eq!(json["context"]["diagnostics"][0]["severity"], "error");
3516 }
3517
3518 #[test]
3519 fn test_text_document_sync_kind_serialization() {
3520 assert_eq!(
3521 serde_json::to_value(&TextDocumentSyncKind::Full).unwrap(),
3522 json!("full")
3523 );
3524 assert_eq!(
3525 serde_json::to_value(&TextDocumentSyncKind::Incremental).unwrap(),
3526 json!("incremental")
3527 );
3528 assert!(serde_json::from_value::<TextDocumentSyncKind>(json!("_future")).is_err());
3529 }
3530
3531 #[test]
3532 fn test_document_event_capabilities_drop_unknown_did_change_sync_kind() {
3533 let caps: NesDocumentEventCapabilities = serde_json::from_value(json!({
3534 "didChange": {
3535 "syncKind": "_future"
3536 }
3537 }))
3538 .unwrap();
3539
3540 assert_eq!(caps.did_change, None);
3541 }
3542
3543 #[test]
3544 fn test_document_did_change_capabilities_requires_sync_kind() {
3545 assert!(serde_json::from_value::<NesDocumentDidChangeCapabilities>(json!({})).is_err());
3546 }
3547
3548 #[test]
3549 fn test_nes_suggest_response_serialization() {
3550 let response = SuggestNesResponse::new(vec![
3551 NesSuggestion::Edit(NesEditSuggestion::new(
3552 "sugg_001",
3553 "file:///path/to/file.rs",
3554 vec![NesTextEdit::new(
3555 Range::new(Position::new(5, 0), Position::new(5, 10)),
3556 "let result = helper();",
3557 )],
3558 )),
3559 NesSuggestion::Jump(NesJumpSuggestion::new(
3560 "sugg_002",
3561 "file:///path/to/other.rs",
3562 Position::new(10, 0),
3563 )),
3564 ]);
3565
3566 let json = serde_json::to_value(&response).unwrap();
3567 assert_eq!(json["suggestions"].as_array().unwrap().len(), 2);
3568 assert_eq!(json["suggestions"][0]["kind"], "edit");
3569 assert_eq!(json["suggestions"][1]["kind"], "jump");
3570 }
3571
3572 #[test]
3573 fn did_change_document_rejects_malformed_content_changes() {
3574 let notification = |content_changes: serde_json::Value| {
3575 serde_json::from_value::<DidChangeDocumentNotification>(json!({
3576 "sessionId": "session_123",
3577 "uri": "file:///path/to/file.rs",
3578 "version": 7,
3579 "contentChanges": content_changes
3580 }))
3581 };
3582
3583 assert!(
3586 notification(json!([
3587 {
3588 "range": {"start": {"line": 3, "character": 0}, "end": {"line": 3, "character": "4"}},
3589 "text": "let"
3590 },
3591 {
3592 "range": {"start": {"line": 9, "character": 2}, "end": {"line": 9, "character": 2}},
3593 "text": "x"
3594 }
3595 ]))
3596 .is_err()
3597 );
3598 assert!(notification(json!("not-an-array")).is_err());
3599 assert_eq!(
3600 notification(serde_json::Value::Null)
3601 .unwrap()
3602 .content_changes,
3603 vec![]
3604 );
3605 }
3606}