mod generated;
pub mod json_rpc;
pub use generated::*;
mod compiletest {}
#[cfg(test)]
#[cfg(all(not(feature = "url"), not(feature = "fluent-uri")))]
mod test {
#![allow(deprecated)]
use std::{
borrow::Cow,
collections::{HashMap, HashSet},
};
use serde_json::json;
use crate::*;
#[test]
fn nullable_field() {
let tdro = TextDocumentRegistrationOptions {
document_selector: None,
};
let tdro_str = serde_json::to_string(&tdro).unwrap();
assert_eq!(tdro_str, r#"{"documentSelector":null}"#);
let tdro = serde_json::from_str::<TextDocumentRegistrationOptions>(&tdro_str).unwrap();
assert_eq!(
tdro,
TextDocumentRegistrationOptions {
document_selector: None
}
);
assert_eq!(tdro, serde_json::from_str("{}").unwrap());
}
#[test]
fn nullable_field_default() {
let ip = InitializeParams::default();
let ip_str = serde_json::to_string(&ip).unwrap();
assert_eq!(
ip_str,
r#"{"processId":null,"rootUri":null,"capabilities":{}}"#
);
assert_eq!(
InitializeParams::default(),
serde_json::from_str(&ip_str).unwrap()
);
let bad_ip_str = r#"{"rootUri":null,"capabilities":{}}"#;
assert_eq!(
InitializeParams::default(),
serde_json::from_str(bad_ip_str).unwrap()
);
}
#[test]
fn optional_field() {
let cp = ColorPresentation {
label: "Label".to_string(),
text_edit: None,
..Default::default()
};
let cp_str = serde_json::to_string(&cp).unwrap();
assert_eq!(cp_str, r#"{"label":"Label"}"#);
let cp = serde_json::from_str::<ColorPresentation>(&cp_str).unwrap();
assert_eq!(
cp,
ColorPresentation {
label: "Label".to_string(),
text_edit: None,
..Default::default()
}
);
assert_eq!(
serde_json::from_str::<ColorPresentation>(r#"{"label":"Label","textEdit":null}"#)
.unwrap(),
cp
);
}
#[test]
fn optional_nullable_field() {
let wfip = WorkspaceFoldersInitializeParams {
workspace_folders: None,
};
let wfip_str = serde_json::to_string(&wfip).unwrap();
assert_eq!(wfip_str, r"{}");
assert_eq!(
serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
wfip
);
let wfip = WorkspaceFoldersInitializeParams {
workspace_folders: Some(crate::WorkspaceFolders::Null),
};
let wfip_str = serde_json::to_string(&wfip).unwrap();
assert_eq!(wfip_str, r#"{"workspaceFolders":null}"#);
assert_eq!(
serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
wfip
);
let wfip = WorkspaceFoldersInitializeParams {
workspace_folders: Some(crate::WorkspaceFolders::WorkspaceFolderList(Vec::new())),
};
let wfip_str = serde_json::to_string(&wfip).unwrap();
assert_eq!(wfip_str, r#"{"workspaceFolders":[]}"#);
assert_eq!(
serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
wfip
);
}
#[test]
fn derives() {
let pos = Position::default();
let table = HashMap::from([(pos, 123)]);
assert_eq!(table.get(&pos), Some(&123));
let range = Range::default();
let table = HashSet::from([range]);
assert!(table.contains(&range));
let doc_sym = DocumentSymbol {
kind: crate::SymbolKind::Function,
name: String::default(),
detail: Option::default(),
tags: Option::default(),
deprecated: Option::default(),
range: Range::default(),
selection_range: Range::default(),
children: Option::default(),
};
let table = HashSet::from([doc_sym.clone()]);
assert!(table.contains(&doc_sym));
let wfip = WorkspaceFoldersInitializeParams {
workspace_folders: Some(Vec::new().into()),
};
let wfip_str = serde_json::to_string(&wfip).unwrap();
assert_eq!(wfip_str, r#"{"workspaceFolders":[]}"#);
assert_eq!(
serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
wfip
);
assert_eq!(WorkspaceFolders::Null, ().into());
let wfip = WorkspaceFoldersInitializeParams {
workspace_folders: Some(().into()),
};
let wfip_str = serde_json::to_string(&wfip).unwrap();
assert_eq!(wfip_str, r#"{"workspaceFolders":null}"#);
assert_eq!(
serde_json::from_str::<WorkspaceFoldersInitializeParams>(&wfip_str).unwrap(),
wfip
);
let wfsc = WorkspaceFoldersServerCapabilities {
change_notifications: Some("some-noti-id".into()),
..Default::default()
};
let wfsc_str = serde_json::to_string(&wfsc).unwrap();
assert_eq!(wfsc_str, r#"{"changeNotifications":"some-noti-id"}"#);
let wfsc = WorkspaceFoldersServerCapabilities {
change_notifications: Some(String::from("some-noti-id").into()),
..Default::default()
};
let wfsc_str = serde_json::to_string(&wfsc).unwrap();
assert_eq!(wfsc_str, r#"{"changeNotifications":"some-noti-id"}"#);
let wfsc = WorkspaceFoldersServerCapabilities {
change_notifications: Some(false.into()),
..Default::default()
};
let wfsc_str = serde_json::to_string(&wfsc).unwrap();
assert_eq!(wfsc_str, r#"{"changeNotifications":false}"#);
let wfsc = WorkspaceFoldersServerCapabilities {
change_notifications: Some('f'.into()),
..Default::default()
};
let wfsc_str = serde_json::to_string(&wfsc).unwrap();
assert_eq!(wfsc_str, r#"{"changeNotifications":"f"}"#);
let boxed_str: Box<str> = Box::from("foo");
let wfsc = WorkspaceFoldersServerCapabilities {
change_notifications: Some(boxed_str.into()),
..Default::default()
};
let wfsc_str = serde_json::to_string(&wfsc).unwrap();
assert_eq!(wfsc_str, r#"{"changeNotifications":"foo"}"#);
}
#[test]
fn special_impls() {
let pos = Position {
line: 2,
character: 0,
};
let pos2 = Position {
line: 1,
character: 9,
};
assert!(pos2 < pos);
let pos3 = pos2;
assert_eq!(pos3, pos2);
let range = Range {
start: pos2,
end: pos,
};
let range2 = range;
assert_eq!(range2, range);
let range3 = Range {
start: Position::default(),
end: Position {
line: 999,
character: 999,
},
};
assert!(range3 < range2);
let range4 = Range::default();
assert!(range4 < range3);
let method: String = LspRequestMethod::TextDocumentOnTypeFormatting.into();
assert_eq!(method, "textDocument/onTypeFormatting");
let method = LspRequestMethod::Shutdown.to_string();
assert_eq!(method, "shutdown");
let method = LspRequestMethod::Custom("foo").to_string();
assert_eq!(method, "foo");
let method = LspNotificationMethod::Custom("foo").to_string();
assert_eq!(method, "foo");
let method = LspNotificationMethod::CancelRequest.to_string();
assert_eq!(method, "$/cancelRequest");
let method = LspNotificationMethod::WorkspaceDidChangeWatchedFiles.to_string();
assert_eq!(method, "workspace/didChangeWatchedFiles");
let wk = WatchKind::Delete;
let wk2 = WatchKind::Create;
assert_eq!(wk | wk2, WatchKind::Custom(5));
assert_eq!(wk | wk2 | WatchKind::Change, WatchKind::Custom(7));
assert_eq!((wk | wk2) & wk, wk);
assert_eq!(wk | wk, wk);
assert_eq!((wk | wk2 | WatchKind::Change) & (wk | wk2), wk | wk2);
assert_eq!(WatchKind::Delete ^ WatchKind::Delete, WatchKind::Custom(0));
assert_eq!(WatchKind::Custom(0) ^ WatchKind::Create, WatchKind::Create);
let mut wk = WatchKind::Custom(0);
wk |= WatchKind::Delete;
assert_eq!(wk, WatchKind::Delete);
wk &= WatchKind::Create;
assert_eq!(wk, WatchKind::Custom(0));
wk ^= WatchKind::Delete;
assert_eq!(wk, WatchKind::Delete);
}
#[test]
fn string_literal_field() {
let wdpe = WorkDoneProgressEnd {
message: Some("change da world. my final message. goodbye".to_string()),
};
let ser = serde_json::to_string(&wdpe).unwrap();
assert_eq!(
ser,
r#"{"message":"change da world. my final message. goodbye","kind":"end"}"#
);
let deser = serde_json::from_str::<WorkDoneProgressEnd>(&ser).unwrap();
assert_eq!(deser, wdpe);
let fake_ser = r#"{"message":"change da world. my final message. goodbye","kind":"begin"}"#;
assert!(serde_json::from_str::<WorkDoneProgressEnd>(fake_ser).is_err());
let doc_change = CreateFile {
uri: "file:///foo.txt".to_string().into(),
options: None,
annotation_id: None,
};
let ser = serde_json::to_string(&doc_change).unwrap();
assert_eq!(ser, r#"{"uri":"file:///foo.txt","kind":"create"}"#);
let ser = r#"{"uri":"file:///foo.txt","kind":"create"}"#;
let deser = serde_json::from_str::<DocumentChange>(ser).unwrap();
assert_eq!(deser, doc_change.into());
let ser = r#"{"uri":"file:///foo.txt","kind":"delete","annotationId":"foo"}"#;
let deser = serde_json::from_str::<DocumentChange>(ser).unwrap();
assert_eq!(
deser,
DocumentChange::DeleteFile(DeleteFile {
uri: crate::Uri("file:///foo.txt".to_string()),
options: None,
annotation_id: Some(String::from("foo"))
})
);
let bad_ser = r#"{"uri":"file:///foo.txt","kind":"delet"}"#;
assert!(serde_json::from_str::<DocumentChange>(bad_ser).is_err());
}
#[test]
fn string_enum() {
let frk = FoldingRangeKind::Comment;
let ser = serde_json::to_string(&frk).unwrap();
assert_eq!(ser, "\"comment\"");
assert_eq!(
serde_json::from_str::<FoldingRangeKind>(&ser).unwrap(),
FoldingRangeKind::Comment
);
let frk = FoldingRangeKind::Custom(Cow::Borrowed("foo"));
let ser = serde_json::to_string(&frk).unwrap();
assert_eq!(ser, "\"foo\"");
assert_eq!(
serde_json::from_str::<FoldingRangeKind>(&ser).unwrap(),
FoldingRangeKind::Custom(Cow::Borrowed("foo"))
);
assert_eq!("foo", frk.as_str());
let mk = MarkupKind::PlainText;
assert_eq!("\"plaintext\"", serde_json::to_string(&mk).unwrap());
assert!(serde_json::from_str::<MarkupKind>("foo").is_err());
assert_eq!("plaintext", mk.as_str());
}
#[test]
fn str_enum_into() {
const CONSTANT: &str = "my_custom_variant";
let _parsed: LspNotificationMethod = CONSTANT.into();
}
#[test]
fn int_enum() {
let sk = SymbolKind::Namespace;
let ser = serde_json::to_string(&sk).unwrap();
assert_eq!(ser, "3");
assert_eq!(
serde_json::from_str::<SymbolKind>(&ser).unwrap(),
SymbolKind::Namespace
);
assert!(serde_json::from_str::<SymbolKind>("299").is_err());
let wk = WatchKind::Custom(123);
let ser = serde_json::to_string(&wk).unwrap();
assert_eq!(ser, "123");
assert_eq!(wk, serde_json::from_str::<WatchKind>(&ser).unwrap());
assert_eq!(
WatchKind::Change,
serde_json::from_str::<WatchKind>("2").unwrap()
);
}
#[test]
fn request_object_from_request() {
let params = TypeDefinitionParams {
work_done_progress_params: crate::WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: crate::PartialResultParams {
partial_result_token: None,
},
text_document_position_params: crate::TextDocumentPositionParams {
text_document: crate::TextDocumentIdentifier { uri: "foo".into() },
position: Position::default(),
},
};
let req = json_rpc::RequestObject::from_request::<TypeDefinitionRequest>(
json_rpc::Id::Number(123),
params.clone(),
);
let ser = serde_json::to_string(&req).unwrap();
assert_eq!(
ser,
r#"{"jsonrpc":"2.0","id":123,"method":"textDocument/typeDefinition","params":{"position":{"character":0,"line":0},"textDocument":{"uri":"foo"}}}"#
);
assert_eq!(req.id(), Some(&json_rpc::Id::Number(123)));
assert_eq!(req.method(), "textDocument/typeDefinition");
assert_eq!(req.params(), Some(&json!(params)));
}
#[test]
fn request_object_from_request_no_params() {
let req = json_rpc::RequestObject::from_request::<WorkspaceFoldersRequest>(
json_rpc::Id::String("foo".into()),
(),
);
let ser = serde_json::to_string(&req).unwrap();
assert_eq!(
ser,
r#"{"jsonrpc":"2.0","id":"foo","method":"workspace/workspaceFolders"}"#
);
}
#[test]
fn request_object_from_notification() {
let noti = json_rpc::RequestObject::from_notification::<InitializedNotification>(
InitializedParams {},
);
let ser = serde_json::to_string(¬i).unwrap();
assert_eq!(
ser,
r#"{"jsonrpc":"2.0","method":"initialized","params":{}}"#
);
assert_eq!(noti.id(), None);
assert_eq!(noti.method(), "initialized");
assert_eq!(noti.params(), Some(&json!(InitializedParams {})));
}
#[test]
fn request_object_from_notification_no_params() {
let noti = json_rpc::RequestObject::from_notification::<ExitNotification>(());
let ser = serde_json::to_string(¬i).unwrap();
assert_eq!(ser, r#"{"jsonrpc":"2.0","method":"exit"}"#);
}
#[test]
fn response_object_from_success() {
let id = json_rpc::Id::Number(123);
let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(
id.clone(),
Some(ImplementationResponse::DefinitionLinkList(Vec::new())),
);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(r#"{"jsonrpc":"2.0","result":[],"id":123}"#, &ser);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(id.clone(), None);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
let res = json_rpc::ResponseObject::from_success::<ImplementationRequest>(id.clone(), None);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
let res = json_rpc::ResponseObject::from_success::<ShowMessageRequest>(id.clone(), None);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
let res = json_rpc::ResponseObject::from_success::<ShowMessageRequest>(
id.clone(),
Some(crate::MessageActionItem {
title: "foo".into(),
}),
);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(
r#"{"jsonrpc":"2.0","result":{"title":"foo"},"id":123}"#,
&ser
);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
let res = json_rpc::ResponseObject::from_success::<CodeLensRefreshRequest>(id, ());
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(r#"{"jsonrpc":"2.0","result":null,"id":123}"#, &ser);
assert_eq!(res, serde_json::from_str(&ser).unwrap());
}
#[test]
fn response_object_from_error() {
let id = json_rpc::Id::Null;
let res = json_rpc::ResponseObject::from_error(
id,
json_rpc::Error {
code: crate::ErrorCodes::ParseError,
message: "invalid format".into(),
data: None,
},
);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(
r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"invalid format"},"id":null}"#,
&ser
);
let id = json_rpc::Id::String("foo-req".into());
let res = json_rpc::ResponseObject::from_error(
id,
json_rpc::Error {
code: crate::ErrorCodes::Custom(-32803),
message: "failed to foo the bar".into(),
data: Some(json!("hi")),
},
);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(
r#"{"jsonrpc":"2.0","error":{"code":-32803,"message":"failed to foo the bar","data":"hi"},"id":"foo-req"}"#,
&ser
);
let id = json_rpc::Id::String("foo-req".into());
let res = json_rpc::ResponseObject::from_error(
id,
json_rpc::Error {
code: crate::ErrorCodes::Custom(crate::LspErrorCodes::ContentModified.into()),
message: "failed to foo the bar".into(),
data: Some(json!("hi")),
},
);
let ser = serde_json::to_string(&res).unwrap();
assert_eq!(
r#"{"jsonrpc":"2.0","error":{"code":-32801,"message":"failed to foo the bar","data":"hi"},"id":"foo-req"}"#,
&ser
);
}
#[test]
fn structures_new_constructor() {
assert_eq!(
Position::new(1, 2),
Position {
line: 1,
character: 2
}
);
assert_eq!(
Range::new(Position::new(0, 0), Position::new(0, 99)),
Range {
start: Position::default(),
end: Position {
line: 0,
character: 99
}
}
);
assert_eq!(
Location::new(Uri("foo".into()), Range::default()),
Location {
uri: Uri("foo".into()),
range: Range::default()
}
);
assert_eq!(
Diagnostic::new(
Range::default(),
Some(DiagnosticSeverity::Warning),
None,
None,
None,
"bad".into(),
None,
None,
None
),
Diagnostic {
range: Range::default(),
message: "bad".into(),
severity: Some(DiagnosticSeverity::Warning),
..Default::default()
}
);
}
#[test]
fn custom_request_object_methods() {
struct ParentModule;
impl Request for ParentModule {
type Params = ();
type Result = Option<DefinitionResponse>;
const METHOD: LspRequestMethod<'_> =
LspRequestMethod::Custom("experimental/parentModule");
const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
}
let req =
json_rpc::RequestObject::from_request::<ParentModule>(json_rpc::Id::Number(123), ());
assert_eq!(
r#"{"jsonrpc":"2.0","id":123,"method":"experimental/parentModule"}"#,
serde_json::to_string(&req).unwrap()
);
struct ServerStatusNotification;
impl Notification for ServerStatusNotification {
type Params = ();
const METHOD: LspNotificationMethod<'_> =
LspNotificationMethod::new("experimental/serverStatus");
const MESSAGE_DIRECTION: MessageDirection = MessageDirection::ClientToServer;
}
let noti = json_rpc::RequestObject::from_notification::<ServerStatusNotification>(());
assert_eq!(
r#"{"jsonrpc":"2.0","method":"experimental/serverStatus"}"#,
serde_json::to_string(¬i).unwrap()
);
let method: &'static str = <ParentModule as Request>::METHOD.as_str();
assert_eq!(method, "experimental/parentModule");
let method = LspRequestMethod::new("asdf");
let method_str: &'static str = method.as_str();
assert_eq!(method_str, "asdf");
let method = LspRequestMethod::Custom("asdf");
let method_str: &'static str = method.as_str();
assert_eq!(method_str, "asdf");
let owned = String::from("workspace/didCreateFiles");
let method: LspNotificationMethod<'_> = owned.as_str().into();
assert_eq!(method, LspNotificationMethod::WorkspaceDidCreateFiles);
let owned = String::from("foo");
let method: LspNotificationMethod<'_> = owned.as_str().into();
assert_eq!(method, LspNotificationMethod::new("foo"));
let method1 = LspRequestMethod::TextDocumentCompletion;
let method2 = method1;
assert_eq!(method1, method2);
#[allow(clippy::match_same_arms)]
match method {
LspNotificationMethod::TextDocumentWillSave => {}
LspNotificationMethod::Custom("foo") => {}
LspNotificationMethod::Custom(_) => {}
_ => {}
}
}
#[test]
fn request_with_partial_results() {
fn foo<R: RequestWithPartialResults>(
_params: R::Params,
_partial_result: R::PartialResult,
) {
}
foo::<DocumentSymbolRequest>(
DocumentSymbolParams {
text_document: TextDocumentIdentifier { uri: "".into() },
work_done_progress_params: WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: PartialResultParams {
partial_result_token: None,
},
},
DocumentSymbolPartialResponse::SymbolInformationList(vec![SymbolInformation {
deprecated: None,
location: Location {
uri: "".into(),
range: Range::default(),
},
base_symbol_information: BaseSymbolInformation {
name: String::new(),
kind: SymbolKind::File,
tags: None,
container_name: None,
},
}]),
);
let partial_result = DocumentSymbolPartialResponse::DocumentSymbolList(Vec::new());
let _ = match partial_result {
DocumentSymbolPartialResponse::SymbolInformationList(_) => 1,
DocumentSymbolPartialResponse::DocumentSymbolList(_) => 2,
};
}
#[test]
#[allow(clippy::similar_names)]
fn semantic_tokens() {
let ste = SemanticTokensEdit {
start: 0,
delete_count: 1,
data: None,
};
let ste_ser = r#"{"start":0,"deleteCount":1}"#;
assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
let ste = SemanticTokensEdit {
start: 0,
delete_count: 1,
data: None,
};
let ste_ser_fake = r#"{"start":0,"deleteCount":1,"data":null}"#;
assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
assert_eq!(ste, serde_json::from_str(ste_ser_fake).unwrap());
let ste = SemanticTokensEdit {
start: 0,
delete_count: 1,
data: Some(vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
]),
};
let ste_ser = r#"{"start":0,"deleteCount":1,"data":[2,5,3,0,3,0,5,4,1,0]}"#;
assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
let ste = SemanticTokensEdit {
start: 0,
delete_count: 1,
data: Some(Vec::new()),
};
let ste_ser = r#"{"start":0,"deleteCount":1,"data":[]}"#;
assert_eq!(serde_json::to_string(&ste).unwrap(), ste_ser);
assert_eq!(ste, serde_json::from_str(ste_ser).unwrap());
let st = SemanticTokens {
result_id: None,
data: Vec::default(),
};
let st_ser = r#"{"data":[]}"#;
assert_eq!(serde_json::to_string(&st).unwrap(), st_ser);
assert_eq!(st, serde_json::from_str(st_ser).unwrap());
let st = SemanticTokens {
result_id: None,
data: vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
],
};
let st_ser = r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#;
assert_eq!(serde_json::to_string(&st).unwrap(), st_ser);
assert_eq!(st, serde_json::from_str(st_ser).unwrap());
let stpr = SemanticTokensPartialResult {
data: vec![
SemanticToken {
delta_line: 2,
delta_start: 5,
length: 3,
token_type: 0,
token_modifiers_bitset: 3,
},
SemanticToken {
delta_line: 0,
delta_start: 5,
length: 4,
token_type: 1,
token_modifiers_bitset: 0,
},
],
};
let stpr_ser = r#"{"data":[2,5,3,0,3,0,5,4,1,0]}"#;
assert_eq!(serde_json::to_string(&stpr).unwrap(), stpr_ser);
assert_eq!(stpr, serde_json::from_str(stpr_ser).unwrap());
let stpr = SemanticTokensPartialResult {
data: Vec::default(),
};
let stpr_ser = r#"{"data":[]}"#;
assert_eq!(serde_json::to_string(&stpr).unwrap(), stpr_ser);
assert_eq!(stpr, serde_json::from_str(stpr_ser).unwrap());
}
#[test]
fn request_macro() {
let req = json_rpc::RequestObject::from_request::<lsp_request!("workspace/workspaceFolders")>(
json_rpc::Id::Number(123),
(),
);
assert_eq!(
r#"{"jsonrpc":"2.0","id":123,"method":"workspace/workspaceFolders"}"#,
serde_json::to_string(&req).unwrap()
);
}
#[test]
fn notification_macro() {
let req = json_rpc::RequestObject::from_notification::<lsp_notification!("exit")>(());
assert_eq!(
r#"{"jsonrpc":"2.0","method":"exit"}"#,
serde_json::to_string(&req).unwrap()
);
}
#[test]
fn tuple_serialization() {
let pil = ParameterInformationLabel::Tuple((1, 2));
assert_eq!("[1,2]", serde_json::to_string(&pil).unwrap());
assert_eq!(pil, serde_json::from_str("[1,2]").unwrap());
}
}
#[cfg(test)]
#[cfg(all(feature = "url", not(feature = "fluent-uri")))]
mod test {
use crate::*;
#[test]
fn url_feature() {
let url = url::Url::parse("file://tmp/foo.txt/").unwrap();
let tdi = TextDocumentIdentifier { uri: url };
let ser = r#"{"uri":"file://tmp/foo.txt/"}"#;
assert_eq!(ser, serde_json::to_string(&tdi).unwrap());
assert_eq!(tdi, serde_json::from_str(ser).unwrap());
}
}
#[cfg(test)]
#[cfg(all(feature = "fluent-uri", not(feature = "url")))]
mod test {
use crate::*;
#[test]
fn url_feature() {
let uri = fluent_uri::Uri::try_from("file://tmp/foo.txt/".to_string()).unwrap();
let tdi = TextDocumentIdentifier { uri };
let ser = r#"{"uri":"file://tmp/foo.txt/"}"#;
assert_eq!(ser, serde_json::to_string(&tdi).unwrap());
assert_eq!(tdi, serde_json::from_str(ser).unwrap());
}
}