1mod generated;
2pub mod json_rpc;
3
4pub use generated::*;
5
6mod compiletest {}
37
38#[cfg(test)]
40#[cfg(all(not(feature = "url"), not(feature = "fluent-uri")))]
41mod test {
42 #![allow(deprecated)]
43 use std::{
44 borrow::Cow,
45 collections::{HashMap, HashSet},
46 };
47
48 use serde_json::json;
49
50 use crate::*;
51
52 #[test]
53 fn nullable_field() {
54 let tdro = TextDocumentRegistrationOptions {
55 document_selector: None,
56 };
57 let tdro_str = serde_json::to_string(&tdro).unwrap();
58 assert_eq!(tdro_str, r#"{"documentSelector":null}"#);
59
60 let tdro = serde_json::from_str::<TextDocumentRegistrationOptions>(&tdro_str).unwrap();
61 assert_eq!(
62 tdro,
63 TextDocumentRegistrationOptions {
64 document_selector: None
65 }
66 );
67
68 assert_eq!(tdro, serde_json::from_str("{}").unwrap());
71 }
72
73 #[test]
74 fn nullable_field_default() {
75 let ip = InitializeParams::default();
76
77 let ip_str = serde_json::to_string(&ip).unwrap();
78
79 assert_eq!(
80 ip_str,
81 r#"{"processId":null,"rootUri":null,"capabilities":{}}"#
82 );
83
84 assert_eq!(
85 InitializeParams::default(),
86 serde_json::from_str(&ip_str).unwrap()
87 );
88
89 let bad_ip_str = r#"{"rootUri":null,"capabilities":{}}"#;
92 assert_eq!(
93 InitializeParams::default(),
94 serde_json::from_str(bad_ip_str).unwrap()
95 );
96 }
97
98 #[test]
99 fn optional_field() {
100 let cp = ColorPresentation {
101 label: "Label".to_string(),
102 text_edit: None,
103 ..Default::default()
104 };
105 let cp_str = serde_json::to_string(&cp).unwrap();
106 assert_eq!(cp_str, r#"{"label":"Label"}"#);
107
108 let cp = serde_json::from_str::<ColorPresentation>(&cp_str).unwrap();
109 assert_eq!(
110 cp,
111 ColorPresentation {
112 label: "Label".to_string(),
113 text_edit: None,
114 ..Default::default()
115 }
116 );
117 assert_eq!(
120 serde_json::from_str::<ColorPresentation>(r#"{"label":"Label","textEdit":null}"#)
121 .unwrap(),
122 cp
123 );
124 }
125
126 #[test]
127 fn optional_nullable_field() {
128 let wfip = WorkspaceFoldersInitializeParams {
129 workspace_folders: None,
130 };
131
132 let wfip_str = serde_json::to_string(&wfip).unwrap();
133
134 assert_eq!(wfip_str, r"{}");
135
136 assert_eq!(
137 serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
138 wfip
139 );
140
141 let wfip = WorkspaceFoldersInitializeParams {
142 workspace_folders: Some(crate::WorkspaceFolders::Null),
143 };
144 let wfip_str = serde_json::to_string(&wfip).unwrap();
145 assert_eq!(wfip_str, r#"{"workspaceFolders":null}"#);
146 assert_eq!(
147 serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
148 wfip
149 );
150
151 let wfip = WorkspaceFoldersInitializeParams {
152 workspace_folders: Some(crate::WorkspaceFolders::WorkspaceFolderList(Vec::new())),
153 };
154 let wfip_str = serde_json::to_string(&wfip).unwrap();
155 assert_eq!(wfip_str, r#"{"workspaceFolders":[]}"#);
156 assert_eq!(
157 serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
158 wfip
159 );
160 }
161
162 #[test]
163 fn derives() {
164 let pos = Position::default();
165 let table = HashMap::from([(pos, 123)]);
166 assert_eq!(table.get(&pos), Some(&123));
167
168 let range = Range::default();
169 let table = HashSet::from([range]);
170 assert!(table.contains(&range));
171
172 let doc_sym = DocumentSymbol {
173 kind: crate::SymbolKind::Function,
174 name: String::default(),
175 detail: Option::default(),
176 tags: Option::default(),
177 deprecated: Option::default(),
178 range: Range::default(),
179 selection_range: Range::default(),
180 children: Option::default(),
181 };
182 let table = HashSet::from([doc_sym.clone()]);
183 assert!(table.contains(&doc_sym));
184
185 let wfip = WorkspaceFoldersInitializeParams {
187 workspace_folders: Some(Vec::new().into()),
188 };
189 let wfip_str = serde_json::to_string(&wfip).unwrap();
190 assert_eq!(wfip_str, r#"{"workspaceFolders":[]}"#);
191 assert_eq!(
192 serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
193 wfip
194 );
195 assert_eq!(WorkspaceFolders::Null, ().into());
196 let wfip = WorkspaceFoldersInitializeParams {
197 workspace_folders: Some(().into()),
198 };
199 let wfip_str = serde_json::to_string(&wfip).unwrap();
200 assert_eq!(wfip_str, r#"{"workspaceFolders":null}"#);
201 assert_eq!(
202 serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
203 wfip
204 );
205 let wfsc = WorkspaceFoldersServerCapabilities {
206 change_notifications: Some("some-noti-id".into()),
207 ..Default::default()
208 };
209 let wfsc_str = serde_json::to_string(&wfsc).unwrap();
210 assert_eq!(wfsc_str, r#"{"changeNotifications":"some-noti-id"}"#);
211 let wfsc = WorkspaceFoldersServerCapabilities {
212 change_notifications: Some(String::from("some-noti-id").into()),
213 ..Default::default()
214 };
215 let wfsc_str = serde_json::to_string(&wfsc).unwrap();
216 assert_eq!(wfsc_str, r#"{"changeNotifications":"some-noti-id"}"#);
217 let wfsc = WorkspaceFoldersServerCapabilities {
218 change_notifications: Some(false.into()),
219 ..Default::default()
220 };
221 let wfsc_str = serde_json::to_string(&wfsc).unwrap();
222 assert_eq!(wfsc_str, r#"{"changeNotifications":false}"#);
223 let wfsc = WorkspaceFoldersServerCapabilities {
224 change_notifications: Some('f'.into()),
225 ..Default::default()
226 };
227 let wfsc_str = serde_json::to_string(&wfsc).unwrap();
228 assert_eq!(wfsc_str, r#"{"changeNotifications":"f"}"#);
229 let boxed_str: Box<str> = Box::from("foo");
230 let wfsc = WorkspaceFoldersServerCapabilities {
231 change_notifications: Some(boxed_str.into()),
232 ..Default::default()
233 };
234 let wfsc_str = serde_json::to_string(&wfsc).unwrap();
235 assert_eq!(wfsc_str, r#"{"changeNotifications":"foo"}"#);
236 }
237
238 #[test]
239 fn special_impls() {
240 let pos = Position {
241 line: 2,
242 character: 0,
243 };
244 let pos2 = Position {
245 line: 1,
246 character: 9,
247 };
248 assert!(pos2 < pos);
249
250 let pos3 = pos2;
252 assert_eq!(pos3, pos2);
253
254 let range = Range {
255 start: pos2,
256 end: pos,
257 };
258 let range2 = range;
260 assert_eq!(range2, range);
261
262 let range3 = Range {
263 start: Position::default(),
264 end: Position {
265 line: 999,
266 character: 999,
267 },
268 };
269 assert!(range3 < range2);
270
271 let range4 = Range::default();
272 assert!(range4 < range3);
273
274 let method: String = LspRequestMethod::TextDocumentOnTypeFormatting.into();
275 assert_eq!(method, "textDocument/onTypeFormatting");
276 let method = LspRequestMethod::Shutdown.to_string();
277 assert_eq!(method, "shutdown");
278 let method = LspRequestMethod::Custom("foo").to_string();
279 assert_eq!(method, "foo");
280 let method = LspNotificationMethod::Custom("foo").to_string();
281 assert_eq!(method, "foo");
282 let method = LspNotificationMethod::CancelRequest.to_string();
283 assert_eq!(method, "$/cancelRequest");
284 let method = LspNotificationMethod::WorkspaceDidChangeWatchedFiles.to_string();
285 assert_eq!(method, "workspace/didChangeWatchedFiles");
286
287 let wk = WatchKind::Delete;
288 let wk2 = WatchKind::Create;
289 assert_eq!(wk | wk2, WatchKind::Custom(5));
290 assert_eq!(wk | wk2 | WatchKind::Change, WatchKind::Custom(7));
291 assert_eq!((wk | wk2) & wk, wk);
292 assert_eq!(wk | wk, wk);
293 assert_eq!((wk | wk2 | WatchKind::Change) & (wk | wk2), wk | wk2);
294 assert_eq!(WatchKind::Delete ^ WatchKind::Delete, WatchKind::Custom(0));
295 assert_eq!(WatchKind::Custom(0) ^ WatchKind::Create, WatchKind::Create);
296 let mut wk = WatchKind::Custom(0);
297 wk |= WatchKind::Delete;
298 assert_eq!(wk, WatchKind::Delete);
299 wk &= WatchKind::Create;
300 assert_eq!(wk, WatchKind::Custom(0));
301 wk ^= WatchKind::Delete;
302 assert_eq!(wk, WatchKind::Delete);
303 }
304
305 #[test]
306 fn string_literal_field() {
307 let wdpe = WorkDoneProgressEnd {
308 message: Some("change da world. my final message. goodbye".to_string()),
309 };
310
311 let ser = serde_json::to_string(&wdpe).unwrap();
312 assert_eq!(
313 ser,
314 r#"{"message":"change da world. my final message. goodbye","kind":"end"}"#
315 );
316
317 let deser = serde_json::from_str::<WorkDoneProgressEnd>(&ser).unwrap();
318 assert_eq!(deser, wdpe);
319
320 let fake_ser = r#"{"message":"change da world. my final message. goodbye","kind":"begin"}"#;
321 assert!(serde_json::from_str::<WorkDoneProgressEnd>(fake_ser).is_err());
322
323 let doc_change = CreateFile {
324 uri: "file:///foo.txt".to_string().into(),
325 options: None,
326 annotation_id: None,
327 };
328 let ser = serde_json::to_string(&doc_change).unwrap();
329 assert_eq!(ser, r#"{"uri":"file:///foo.txt","kind":"create"}"#);
330
331 let ser = r#"{"uri":"file:///foo.txt","kind":"create"}"#;
332 let deser = serde_json::from_str::<DocumentChange>(ser).unwrap();
333 assert_eq!(deser, doc_change.into());
334 let ser = r#"{"uri":"file:///foo.txt","kind":"delete","annotationId":"foo"}"#;
335 let deser = serde_json::from_str::<DocumentChange>(ser).unwrap();
336 assert_eq!(
337 deser,
338 DocumentChange::DeleteFile(DeleteFile {
339 uri: crate::Uri("file:///foo.txt".to_string()),
340 options: None,
341 annotation_id: Some(String::from("foo"))
342 })
343 );
344 let bad_ser = r#"{"uri":"file:///foo.txt","kind":"delet"}"#;
345 assert!(serde_json::from_str::<DocumentChange>(bad_ser).is_err());
346 }
347
348 #[test]
349 fn string_enum() {
350 let frk = FoldingRangeKind::Comment;
351 let ser = serde_json::to_string(&frk).unwrap();
352
353 assert_eq!(ser, "\"comment\"");
354 assert_eq!(
355 serde_json::from_str::<FoldingRangeKind>(&ser).unwrap(),
356 FoldingRangeKind::Comment
357 );
358
359 let frk = FoldingRangeKind::Custom(Cow::Borrowed("foo"));
360 let ser = serde_json::to_string(&frk).unwrap();
361
362 assert_eq!(ser, "\"foo\"");
363 assert_eq!(
364 serde_json::from_str::<FoldingRangeKind>(&ser).unwrap(),
365 FoldingRangeKind::Custom(Cow::Borrowed("foo"))
366 );
367 assert_eq!("foo", frk.as_str());
368
369 let mk = MarkupKind::PlainText;
370 assert_eq!("\"plaintext\"", serde_json::to_string(&mk).unwrap());
371 assert!(serde_json::from_str::<MarkupKind>("foo").is_err());
372 assert_eq!("plaintext", mk.as_str());
373 }
374
375 #[test]
376 fn str_enum_into() {
377 const CONSTANT: &str = "my_custom_variant";
378 let _parsed: LspNotificationMethod = CONSTANT.into();
379 }
380
381 #[test]
382 fn int_enum() {
383 let sk = SymbolKind::Namespace;
384 let ser = serde_json::to_string(&sk).unwrap();
385
386 assert_eq!(ser, "3");
387 assert_eq!(
388 serde_json::from_str::<SymbolKind>(&ser).unwrap(),
389 SymbolKind::Namespace
390 );
391 assert!(serde_json::from_str::<SymbolKind>("299").is_ok());
392
393 let wk = WatchKind::Custom(123);
394 let ser = serde_json::to_string(&wk).unwrap();
395
396 assert_eq!(ser, "123");
397 assert_eq!(wk, serde_json::from_str::<WatchKind>(&ser).unwrap());
398 assert_eq!(
399 WatchKind::Change,
400 serde_json::from_str::<WatchKind>("2").unwrap()
401 );
402 }
403
404 #[test]
405 fn request_object_from_request() {
406 let params = TypeDefinitionParams {
407 work_done_progress_params: crate::WorkDoneProgressParams {
408 work_done_token: None,
409 },
410 partial_result_params: crate::PartialResultParams {
411 partial_result_token: None,
412 },
413 text_document_position_params: crate::TextDocumentPositionParams {
414 text_document: crate::TextDocumentIdentifier { uri: "foo".into() },
415 position: Position::default(),
416 },
417 };
418 let req = json_rpc::RequestObject::from_request::<TypeDefinitionRequest>(
419 json_rpc::Id::Number(123),
420 params.clone(),
421 );
422
423 let ser = serde_json::to_string(&req).unwrap();
424
425 assert_eq!(
426 ser,
427 r#"{"jsonrpc":"2.0","id":123,"method":"textDocument/typeDefinition","params":{"position":{"character":0,"line":0},"textDocument":{"uri":"foo"}}}"#
428 );
429 assert_eq!(req.id(), Some(&json_rpc::Id::Number(123)));
430 assert_eq!(req.method(), "textDocument/typeDefinition");
431 assert_eq!(req.params(), Some(&json!(params)));
432 }
433
434 #[test]
435 fn request_object_from_request_no_params() {
436 let req = json_rpc::RequestObject::from_request::<WorkspaceFoldersRequest>(
437 json_rpc::Id::String("foo".into()),
438 (),
439 );
440
441 let ser = serde_json::to_string(&req).unwrap();
442
443 assert_eq!(
444 ser,
445 r#"{"jsonrpc":"2.0","id":"foo","method":"workspace/workspaceFolders"}"#
446 );
447 }
448
449 #[test]
450 fn request_object_from_notification() {
451 let noti = json_rpc::RequestObject::from_notification::<InitializedNotification>(
452 InitializedParams {},
453 );
454
455 let ser = serde_json::to_string(¬i).unwrap();
456
457 assert_eq!(
458 ser,
459 r#"{"jsonrpc":"2.0","method":"initialized","params":{}}"#
460 );
461 assert_eq!(noti.id(), None);
462 assert_eq!(noti.method(), "initialized");
463 assert_eq!(noti.params(), Some(&json!(InitializedParams {})));
464 }
465
466 #[test]
467 fn request_object_from_notification_no_params() {
468 let noti = json_rpc::RequestObject::from_notification::<ExitNotification>(());
469
470 let ser = serde_json::to_string(¬i).unwrap();
471
472 assert_eq!(ser, r#"{"jsonrpc":"2.0","method":"exit"}"#);
473 }
474
475 #[test]
476 fn response_object_from_success() {
477 let id = json_rpc::Id::Number(123);
478
479 let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(
480 id.clone(),
481 Some(ImplementationResponse::DefinitionLinkList(Vec::new())),
482 );
483
484 let ser = serde_json::to_string(&res).unwrap();
485 assert_eq!(r#"{"jsonrpc":"2.0","result":[],"id":123}"#, &ser);
486 assert_eq!(res, serde_json::from_str(&ser).unwrap());
487
488 let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(id.clone(), None);
489
490 let ser = serde_json::to_string(&res).unwrap();
491 assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
492 assert_eq!(res, serde_json::from_str(&ser).unwrap());
493
494 let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(id.clone(), None);
495
496 let ser = serde_json::to_string(&res).unwrap();
497 assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
498 assert_eq!(res, serde_json::from_str(&ser).unwrap());
499
500 let res = json_rpc::ResponseObject::from_success::<ShowMessageRequest>(id.clone(), None);
501
502 let ser = serde_json::to_string(&res).unwrap();
503 assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
504 assert_eq!(res, serde_json::from_str(&ser).unwrap());
505
506 let res = json_rpc::ResponseObject::from_success::<ShowMessageRequest>(
507 id.clone(),
508 Some(MessageActionItem {
509 title: "foo".into(),
510 properties: HashMap::default(),
511 }),
512 );
513
514 let ser = serde_json::to_string(&res).unwrap();
515 assert_eq!(
516 r#"{"jsonrpc":"2.0","result":{"title":"foo"},"id":123}"#,
517 &ser
518 );
519 assert_eq!(res, serde_json::from_str(&ser).unwrap());
520
521 let res = json_rpc::ResponseObject::from_success::<ShowMessageRequest>(
522 id.clone(),
523 Some(MessageActionItem {
524 title: "foo".into(),
525 properties: HashMap::from([(
526 String::from("bar"),
527 MessageActionItemProperty::Int(321),
528 )]),
529 }),
530 );
531
532 let ser = serde_json::to_string(&res).unwrap();
533 assert_eq!(
534 r#"{"jsonrpc":"2.0","result":{"bar":321,"title":"foo"},"id":123}"#,
535 &ser
536 );
537 assert_eq!(res, serde_json::from_str(&ser).unwrap());
538
539 let res = json_rpc::ResponseObject::from_success::<CodeLensRefreshRequest>(id, ());
540
541 let ser = serde_json::to_string(&res).unwrap();
542 assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
543 assert_eq!(res, serde_json::from_str(&ser).unwrap());
544 }
545
546 #[test]
547 fn response_object_from_error() {
548 let id = json_rpc::Id::Null;
549 let res = json_rpc::ResponseObject::from_error(
550 id,
551 json_rpc::Error {
552 code: crate::ErrorCodes::ParseError,
553 message: "invalid format".into(),
554 data: None,
555 },
556 );
557
558 let ser = serde_json::to_string(&res).unwrap();
559 assert_eq!(
560 r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"invalid format"},"id":null}"#,
561 &ser
562 );
563
564 let id = json_rpc::Id::String("foo-req".into());
565 let res = json_rpc::ResponseObject::from_error(
566 id,
567 json_rpc::Error {
568 code: crate::ErrorCodes::Custom(-32803),
569 message: "failed to foo the bar".into(),
570 data: Some(json!("hi")),
571 },
572 );
573
574 let ser = serde_json::to_string(&res).unwrap();
575 assert_eq!(
576 r#"{"jsonrpc":"2.0","error":{"code":-32803,"message":"failed to foo the bar","data":"hi"},"id":"foo-req"}"#,
577 &ser
578 );
579
580 let id = json_rpc::Id::String("foo-req".into());
581 let res = json_rpc::ResponseObject::from_error(
582 id,
583 json_rpc::Error {
584 code: crate::ErrorCodes::Custom(crate::LspErrorCodes::ContentModified.into()),
585 message: "failed to foo the bar".into(),
586 data: Some(json!("hi")),
587 },
588 );
589
590 let ser = serde_json::to_string(&res).unwrap();
591 assert_eq!(
592 r#"{"jsonrpc":"2.0","error":{"code":-32801,"message":"failed to foo the bar","data":"hi"},"id":"foo-req"}"#,
593 &ser
594 );
595 }
596
597 #[test]
598 fn structures_new_constructor() {
599 assert_eq!(
600 Position::new(1, 2),
601 Position {
602 line: 1,
603 character: 2
604 }
605 );
606 assert_eq!(
607 Range::new(Position::new(0, 0), Position::new(0, 99)),
608 Range {
609 start: Position::default(),
610 end: Position {
611 line: 0,
612 character: 99
613 }
614 }
615 );
616
617 assert_eq!(
618 Location::new(Uri("foo".into()), Range::default()),
619 Location {
620 uri: Uri("foo".into()),
621 range: Range::default()
622 }
623 );
624
625 assert_eq!(
627 Diagnostic::new(
628 Range::default(),
629 Some(DiagnosticSeverity::Warning),
630 None,
631 None,
632 None,
633 "bad".into(),
634 None,
635 None,
636 None
637 ),
638 Diagnostic {
639 range: Range::default(),
640 message: "bad".into(),
641 severity: Some(DiagnosticSeverity::Warning),
642 ..Default::default()
643 }
644 );
645 }
646
647 #[test]
648 fn custom_request_object_methods() {
649 struct ParentModule;
650 impl Request for ParentModule {
651 type Params = ();
652 type Result = Option<DefinitionResponse>;
653 const METHOD: LspRequestMethod<'_> =
654 LspRequestMethod::Custom("experimental/parentModule");
655 const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
656 }
657
658 let req =
659 json_rpc::RequestObject::from_request::<ParentModule>(json_rpc::Id::Number(123), ());
660 assert_eq!(
661 r#"{"jsonrpc":"2.0","id":123,"method":"experimental/parentModule"}"#,
662 serde_json::to_string(&req).unwrap()
663 );
664
665 struct ServerStatusNotification;
666 impl Notification for ServerStatusNotification {
667 type Params = ();
668 const METHOD: LspNotificationMethod<'_> =
669 LspNotificationMethod::new("experimental/serverStatus");
670 const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
671 }
672
673 let noti = json_rpc::RequestObject::from_notification::<ServerStatusNotification>(());
674 assert_eq!(
675 r#"{"jsonrpc":"2.0","method":"experimental/serverStatus"}"#,
676 serde_json::to_string(¬i).unwrap()
677 );
678
679 let method: &'static str = <ParentModule as Request>::METHOD.as_str();
681 assert_eq!(method, "experimental/parentModule");
682 let method = LspRequestMethod::new("asdf");
683 let method_str: &'static str = method.as_str();
684 assert_eq!(method_str, "asdf");
685 let method = LspRequestMethod::Custom("asdf");
686 let method_str: &'static str = method.as_str();
687 assert_eq!(method_str, "asdf");
688 let owned = String::from("workspace/didCreateFiles");
689 let method: LspNotificationMethod<'_> = owned.as_str().into();
690 assert_eq!(method, LspNotificationMethod::WorkspaceDidCreateFiles);
691 let owned = String::from("foo");
692 let method: LspNotificationMethod<'_> = owned.as_str().into();
693 assert_eq!(method, LspNotificationMethod::new("foo"));
694 let method1 = LspRequestMethod::TextDocumentCompletion;
696 let method2 = method1;
697 assert_eq!(method1, method2);
698 #[allow(clippy::match_same_arms)]
700 match method {
701 LspNotificationMethod::TextDocumentWillSave => {}
702 LspNotificationMethod::Custom("foo") => {}
703 LspNotificationMethod::Custom(_) => {}
704 _ => {}
705 }
706 }
707
708 #[test]
709 fn request_with_partial_results() {
710 fn foo<R: RequestWithPartialResults>(
711 _params: R::Params,
712 _partial_result: R::PartialResult,
713 ) {
714 }
716
717 foo::<DocumentSymbolRequest>(
718 DocumentSymbolParams {
719 text_document: TextDocumentIdentifier { uri: "".into() },
720 work_done_progress_params: WorkDoneProgressParams {
721 work_done_token: None,
722 },
723 partial_result_params: PartialResultParams {
724 partial_result_token: None,
725 },
726 },
727 DocumentSymbolPartialResponse::SymbolInformationList(vec![SymbolInformation {
728 deprecated: None,
729 location: Location {
730 uri: "".into(),
731 range: Range::default(),
732 },
733 base_symbol_information: BaseSymbolInformation {
734 name: String::new(),
735 kind: SymbolKind::File,
736 tags: None,
737 container_name: None,
738 },
739 }]),
740 );
741
742 let partial_result = DocumentSymbolPartialResponse::DocumentSymbolList(Vec::new());
743 let _ = match partial_result {
744 DocumentSymbolPartialResponse::SymbolInformationList(_) => 1,
745 DocumentSymbolPartialResponse::DocumentSymbolList(_) => 2,
746 };
748 }
749
750 #[test]
751 #[allow(clippy::similar_names)]
752 fn semantic_tokens() {
753 let ste = SemanticTokensEdit {
754 start: 0,
755 delete_count: 1,
756 data: None,
757 };
758 let ste_ser = r#"{"start":0,"deleteCount":1}"#;
759 assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
760 assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
761
762 let ste = SemanticTokensEdit {
763 start: 0,
764 delete_count: 1,
765 data: None,
766 };
767 let ste_ser_fake = r#"{"start":0,"deleteCount":1,"data":null}"#;
768 assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
769 assert_eq!(ste, serde_json::from_str(ste_ser_fake).unwrap());
771
772 let ste = SemanticTokensEdit {
773 start: 0,
774 delete_count: 1,
775 data: Some(vec![2, 5, 3, 4, 1, 0]),
776 };
777 let ste_ser = r#"{"start":0,"deleteCount":1,"data":[2,5,3,4,1,0]}"#;
778 assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
779 assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
780
781 let ste = SemanticTokensEdit {
782 start: 0,
783 delete_count: 1,
784 data: Some(Vec::new()),
785 };
786 let ste_ser = r#"{"start":0,"deleteCount":1,"data":[]}"#;
787 assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
788 assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
789
790 let st = SemanticTokens {
791 result_id: None,
792 data: Vec::default(),
793 };
794 let st_ser = r#"{"data":[]}"#;
795 assert_eq!(serde_json::to_string(&st).unwrap(), st_ser);
796 assert_eq!(st, serde_json::from_str(st_ser).unwrap());
797
798 let st = SemanticTokens {
799 result_id: None,
800 data: vec![
801 SemanticToken {
802 delta_line: 2,
803 delta_start: 5,
804 length: 3,
805 token_type: 0,
806 token_modifiers_bitset: 3,
807 },
808 SemanticToken {
809 delta_line: 0,
810 delta_start: 5,
811 length: 4,
812 token_type: 1,
813 token_modifiers_bitset: 0,
814 },
815 ],
816 };
817 let st_ser = r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#;
818 assert_eq!(serde_json::to_string(&st).unwrap(), st_ser);
819 assert_eq!(st, serde_json::from_str(st_ser).unwrap());
820
821 let stpr = SemanticTokensPartialResult {
822 data: vec![
823 SemanticToken {
824 delta_line: 2,
825 delta_start: 5,
826 length: 3,
827 token_type: 0,
828 token_modifiers_bitset: 3,
829 },
830 SemanticToken {
831 delta_line: 0,
832 delta_start: 5,
833 length: 4,
834 token_type: 1,
835 token_modifiers_bitset: 0,
836 },
837 ],
838 };
839 let stpr_ser = r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#;
840 assert_eq!(serde_json::to_string(&stpr).unwrap(), stpr_ser);
841 assert_eq!(stpr, serde_json::from_str(stpr_ser).unwrap());
842
843 let stpr = SemanticTokensPartialResult {
844 data: Vec::default(),
845 };
846 let stpr_ser = r#"{"data":[]}"#;
847 assert_eq!(serde_json::to_string(&stpr).unwrap(), stpr_ser);
848 assert_eq!(stpr, serde_json::from_str(stpr_ser).unwrap());
849
850 let slice: [u32; 5] = [1, 2, 3, 4, 5];
851 let token: SemanticToken = slice.into();
852 assert_eq!(
853 token,
854 SemanticToken {
855 delta_line: 1,
856 delta_start: 2,
857 length: 3,
858 token_type: 4,
859 token_modifiers_bitset: 5,
860 }
861 );
862 let slice: [u32; 5] = token.into();
863 assert_eq!(slice, [1, 2, 3, 4, 5]);
864 }
865
866 #[test]
867 fn request_macro() {
868 let req = json_rpc::RequestObject::from_request::<lsp_request!("workspace/workspaceFolders")>(
869 json_rpc::Id::Number(123),
870 (),
871 );
872
873 assert_eq!(
874 r#"{"jsonrpc":"2.0","id":123,"method":"workspace/workspaceFolders"}"#,
875 serde_json::to_string(&req).unwrap()
876 );
877 }
878
879 #[test]
880 fn notification_macro() {
881 let req = json_rpc::RequestObject::from_notification::<lsp_notification!("exit")>(());
882
883 assert_eq!(
884 r#"{"jsonrpc":"2.0","method":"exit"}"#,
885 serde_json::to_string(&req).unwrap()
886 );
887 }
888
889 #[test]
890 fn tuple_serialization() {
891 let pil = ParameterInformationLabel::Tuple((1, 2));
892 assert_eq!("[1,2]", serde_json::to_string(&pil).unwrap());
893 assert_eq!(pil, serde_json::from_str("[1,2]").unwrap());
894 }
895
896 #[test]
897 fn lsp_object_derives() {
898 let _: HashMap<NotebookCell, i32> = HashMap::from([(
900 NotebookCell::new(NotebookCellKind::Code, Uri("foo".to_owned()), None, None),
901 123,
902 )]);
903
904 let _: HashMap<SemanticTokensRegistrationOptions, i32> =
906 HashMap::from([(SemanticTokensRegistrationOptions::default(), 123)]);
907
908 let _: HashMap<Command, i32> = HashMap::from([(Command::default(), 123)]);
910 }
911
912 #[test]
913 fn hover_contents() {
914 let contents = Contents::MarkedStringList(vec![
915 MarkedString::String("Foo".to_owned()),
916 MarkedString::String("Bar".to_owned()),
917 ]);
918
919 let ser = serde_json::to_string(&contents).unwrap();
921 assert_eq!(ser, r#"["Foo","Bar"]"#);
922 assert_eq!(contents, serde_json::from_str(&ser).unwrap());
923
924 let contents = Contents::MarkedString(MarkedString::String("Foo".to_owned()));
925
926 let ser = serde_json::to_string(&contents).unwrap();
927 assert_eq!(ser, r#""Foo""#);
928 assert_eq!(contents, serde_json::from_str(&ser).unwrap());
929
930 let contents = Contents::MarkupContent(MarkupContent {
931 kind: MarkupKind::Markdown,
932 value: "foo".to_owned(),
933 });
934
935 let ser = serde_json::to_string(&contents).unwrap();
936 assert_eq!(ser, r#"{"kind":"markdown","value":"foo"}"#);
937 assert_eq!(contents, serde_json::from_str(&ser).unwrap());
938 }
939}
940
941#[cfg(test)]
943#[cfg(all(feature = "url", not(feature = "fluent-uri")))]
944mod test {
945 use crate::*;
946
947 #[test]
948 fn url_feature() {
949 let url = url::Url::parse("file://tmp/foo.txt/").unwrap();
950 let tdi = TextDocumentIdentifier { uri: url };
951 let ser = r#"{"uri":"file://tmp/foo.txt/"}"#;
952
953 assert_eq!(ser, serde_json::to_string(&tdi).unwrap());
954 assert_eq!(tdi, serde_json::from_str(ser).unwrap());
955 }
956}
957
958#[cfg(test)]
960#[cfg(all(feature = "fluent-uri", not(feature = "url")))]
961mod test {
962 use crate::*;
963
964 #[test]
965 fn url_feature() {
966 let uri = fluent_uri::Uri::try_from("file://tmp/foo.txt/".to_string()).unwrap();
967 let tdi = TextDocumentIdentifier { uri };
968 let ser = r#"{"uri":"file://tmp/foo.txt/"}"#;
969
970 assert_eq!(ser, serde_json::to_string(&tdi).unwrap());
971 assert_eq!(tdi, serde_json::from_str(ser).unwrap());
972 }
973}