#![forbid(unsafe_code)]
use lsp_types as lsp;
use serde::{Deserialize, Serialize};
mod convert;
pub type Id = lsp::NumberOrString;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Entry {
pub id: Id,
#[serde(flatten)]
pub element: Element,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "type")]
pub enum Element {
Vertex(Vertex),
Edge(Edge),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "label")]
pub enum Vertex {
Project(Project),
Document(Document),
Range(Range),
ResultSet,
#[serde(rename = "$event")]
Event(Event),
Moniker(Moniker),
PackageInformation(PackageInformation),
MetaData(MetaData),
DefinitionResult,
DeclarationResult,
HoverResult {
result: lsp::Hover,
},
ReferenceResult,
ImplementationResult,
TypeDefinitionResult,
FoldingRangeResult {
result: Vec<lsp::FoldingRange>,
},
DocumentLinkResult {
result: Vec<lsp::DocumentLink>,
},
DocumentSymbolResult {
result: DocumentSymbolResult,
},
DiagnosticResult {
result: Vec<lsp::Diagnostic>,
},
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Project {
pub kind: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub resource: Option<lsp::Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contents: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Document {
pub uri: lsp::Url,
pub language_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub contents: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Range {
#[serde(flatten)]
pub range: lsp::Range,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<RangeTag>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "type")]
pub enum RangeTag {
Declaration(DeclarationTag),
Definition(DefinitionTag),
Reference(ReferenceTag),
Unknown(UnknownTag),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DeclarationTag {
pub text: String,
pub kind: lsp::SymbolKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated: Option<bool>,
pub full_range: lsp::Range,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DefinitionTag {
pub text: String,
pub kind: lsp::SymbolKind,
#[serde(skip_serializing_if = "Option::is_none")]
pub deprecated: Option<bool>,
pub full_range: lsp::Range,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReferenceTag {
pub text: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct UnknownTag {
pub text: String,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Event {
pub kind: EventKind,
pub scope: EventScope,
pub data: Id,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EventKind {
Begin,
End,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EventScope {
Document,
Project,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Moniker {
pub scheme: String,
pub identifier: String,
pub kind: Option<MonikerKind>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PackageInformation {
pub name: String,
pub manager: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<lsp::Url>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contents: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub repository: Option<Repository>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Repository {
#[serde(rename = "type")]
pub r#type: String,
pub url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub commit_id: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum MonikerKind {
Import,
Export,
Local,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetaData {
pub version: String,
pub project_root: lsp::Url,
pub position_encoding: MetaDataPositionEncoding,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_info: Option<MetaDataToolInfo>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum MetaDataPositionEncoding {
#[serde(rename = "utf-16")]
Utf16,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MetaDataToolInfo {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub args: Option<Vec<String>>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(untagged)]
pub enum DocumentSymbolResult {
DocumentSymbols(Vec<lsp::DocumentSymbol>),
RangeBasedDocumentSymbols(Vec<RangeBasedDocumentSymbol>),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RangeBasedDocumentSymbol {
pub id: Id,
#[serde(skip_serializing_if = "Option::is_none")]
pub children: Option<Vec<RangeBasedDocumentSymbol>>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
#[serde(tag = "label")]
pub enum Edge {
Contains(E1N),
Next(E11),
Item(Item),
Moniker(E11),
NextMoniker(E11),
PackageInformation(E11),
#[serde(rename = "textDocument/definition")]
Definition(E11),
#[serde(rename = "textDocument/declaration")]
Declaration(E11),
#[serde(rename = "textDocument/hover")]
Hover(E11),
#[serde(rename = "textDocument/references")]
References(E11),
#[serde(rename = "textDocument/implementation")]
Implementation(E11),
#[serde(rename = "textDocument/typeDefinition")]
TypeDefinition(E11),
#[serde(rename = "textDocument/foldingRange")]
FoldingRange(E11),
#[serde(rename = "textDocument/documentLink")]
DocumentLink(E11),
#[serde(rename = "textDocument/documentSymbol")]
DocumentSymbol(E11),
#[serde(rename = "textDocument/diagnostic")]
Diagnostic(E11),
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct E11 {
pub out_v: Id,
pub in_v: Id,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct E1N {
pub out_v: Id,
pub in_vs: Vec<Id>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Item {
pub out_v: Id,
pub in_vs: Vec<Id>,
pub document: Id,
#[serde(skip_serializing_if = "Option::is_none")]
pub property: Option<ItemProperty>,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ItemProperty {
Definitions,
Declarations,
References,
ReferenceResults,
ImplementationResults,
}
#[cfg(test)]
mod tests {
use super::*;
use lsp_types::{HoverContents, LanguageString, MarkedString, Position};
macro_rules! assert_serde {
($text:ident, $entry:ident) => {
assert_eq!(
serde_json::from_str::<serde_json::Value>(&$text).unwrap(),
serde_json::to_value(&$entry).unwrap()
);
assert_eq!(serde_json::from_str::<Entry>(&$text).unwrap(), $entry);
};
}
#[test]
fn project() {
let text = r#"{ "id": 1, "type": "vertex", "label": "project", "resource": "file:///Users/dirkb/tsconfig.json", "kind": "typescript"}"#;
let entry = Entry {
id: Id::Number(1),
element: Element::Vertex(Vertex::Project(Project {
resource: Some(lsp::Url::parse("file:///Users/dirkb/tsconfig.json").unwrap()),
kind: "typescript".to_owned(),
contents: None,
})),
};
assert_serde!(text, entry);
}
#[test]
fn document() {
let text = r#"{ "id": 1, "type": "vertex", "label": "document", "uri": "file:///Users/dirkb/sample.ts", "languageId": "typescript" }"#;
let entry = Entry {
id: Id::Number(1),
element: Element::Vertex(Vertex::Document(Document {
uri: lsp::Url::parse("file:///Users/dirkb/sample.ts").unwrap(),
language_id: "typescript".to_owned(),
contents: None,
})),
};
assert_serde!(text, entry);
}
#[test]
fn event_document() {
let text = r#"[
{ "id": 5, "type": "vertex", "label": "$event", "kind": "begin", "scope": "document", "data": 4 },
{ "id": 53, "type": "vertex", "label": "$event", "kind": "end", "scope": "document", "data": 4 }
]"#;
let elems = vec![
Entry {
id: Id::Number(5),
element: Element::Vertex(Vertex::Event(Event {
kind: EventKind::Begin,
scope: EventScope::Document,
data: Id::Number(4),
})),
},
Entry {
id: Id::Number(53),
element: Element::Vertex(Vertex::Event(Event {
kind: EventKind::End,
scope: EventScope::Document,
data: Id::Number(4),
})),
},
];
assert_eq!(
serde_json::from_str::<serde_json::Value>(&text).unwrap(),
serde_json::to_value(&elems).unwrap()
);
assert_eq!(serde_json::from_str::<Vec<Entry>>(&text).unwrap(), elems);
}
#[test]
fn event_project() {
let text = r#"[
{ "id": 3, "type": "vertex", "label": "$event", "kind": "begin", "scope": "project", "data": 2 },
{ "id": 55, "type": "vertex", "label": "$event", "kind": "end", "scope": "project", "data": 2 }
]"#;
let elems = vec![
Entry {
id: Id::Number(3),
element: Element::Vertex(Vertex::Event(Event {
kind: EventKind::Begin,
scope: EventScope::Project,
data: Id::Number(2),
})),
},
Entry {
id: Id::Number(55),
element: Element::Vertex(Vertex::Event(Event {
kind: EventKind::End,
scope: EventScope::Project,
data: Id::Number(2),
})),
},
];
assert_eq!(
serde_json::from_str::<serde_json::Value>(&text).unwrap(),
serde_json::to_value(&elems).unwrap()
);
assert_eq!(serde_json::from_str::<Vec<Entry>>(&text).unwrap(), elems);
}
#[test]
fn moniker_vertex() {
let text = r#"{ "id": 12, "type": "vertex", "label": "moniker", "kind": "export", "scheme": "tsc", "identifier": "lib/index:func" }"#;
let entry = Entry {
id: Id::Number(12),
element: Element::Vertex(Vertex::Moniker(Moniker {
kind: Some(MonikerKind::Export),
scheme: "tsc".to_owned(),
identifier: "lib/index:func".to_owned(),
})),
};
assert_serde!(text, entry);
}
#[test]
fn moniker_edge() {
let text = r#"{ "id": 13, "type": "edge", "label": "moniker", "outV": 11, "inV": 12 }"#;
let entry = Entry {
id: Id::Number(13),
element: Element::Edge(Edge::Moniker(E11 {
out_v: Id::Number(11),
in_v: Id::Number(12),
})),
};
assert_serde!(text, entry);
}
#[test]
fn next_moniker() {
let text = r#"{ "id": 985, "type": "edge", "label": "nextMoniker", "outV": 12, "inV": 987 }
"#;
let entry = Entry {
id: Id::Number(985),
element: Element::Edge(Edge::NextMoniker(E11 {
out_v: Id::Number(12),
in_v: Id::Number(987),
})),
};
assert_serde!(text, entry);
}
#[test]
fn package_information_vertex() {
let text = r#"{ "id": 991, "type": "vertex", "label": "packageInformation", "name": "mobx", "manager": "npm", "version": "5.6.0", "repository": { "type": "git", "url": "git+https://github.com/mobxjs/mobx.git" } }"#;
let entry = Entry {
id: Id::Number(991),
element: Element::Vertex(Vertex::PackageInformation(PackageInformation {
name: "mobx".to_owned(),
manager: "npm".to_owned(),
uri: None,
contents: None,
version: Some("5.6.0".to_owned()),
repository: Some(Repository {
r#type: "git".to_owned(),
url: "git+https://github.com/mobxjs/mobx.git".to_owned(),
commit_id: None,
}),
})),
};
assert_serde!(text, entry);
}
#[test]
fn package_information_edge() {
let text = r#"{ "id": 983, "type": "edge", "label": "packageInformation", "outV": 984, "inV": 991 }"#;
let entry = Entry {
id: Id::Number(983),
element: Element::Edge(Edge::PackageInformation(E11 {
out_v: Id::Number(984),
in_v: Id::Number(991),
})),
};
assert_serde!(text, entry);
}
#[test]
fn range() {
let text = r#"{ "id": 4, "type": "vertex", "label": "range", "start": { "line": 0, "character": 9 }, "end": { "line": 0, "character": 12 } }"#;
let entry = Entry {
id: Id::Number(4),
element: Element::Vertex(Vertex::Range(Range {
range: lsp::Range {
start: lsp::Position {
line: 0,
character: 9,
},
end: lsp::Position {
line: 0,
character: 12,
},
},
tag: None,
})),
};
assert_serde!(text, entry);
}
#[test]
fn range_tagged() {
let text = r#"{ "id": 7, "type": "vertex", "label": "range",
"start": { "line": 0, "character": 9 }, "end": { "line": 0, "character": 14 },
"tag": { "type": "definition", "text": "hello", "kind": 12, "fullRange": { "start": { "line": 0, "character": 0 }, "end": { "line": 1, "character": 1 } } }
}"#;
let entry = Entry {
id: Id::Number(7),
element: Element::Vertex(Vertex::Range(Range {
range: lsp::Range {
start: lsp::Position {
line: 0,
character: 9,
},
end: lsp::Position {
line: 0,
character: 14,
},
},
tag: Some(RangeTag::Definition(DefinitionTag {
text: "hello".to_owned(),
kind: lsp::SymbolKind::Function,
deprecated: None,
full_range: lsp::Range {
start: lsp::Position {
line: 0,
character: 0,
},
end: lsp::Position {
line: 1,
character: 1,
},
},
detail: None,
})),
})),
};
assert_serde!(text, entry);
}
#[test]
fn result_set() {
let text = r#"{ "id": 2, "type": "vertex", "label": "resultSet" }"#;
let entry = Entry {
id: Id::Number(2),
element: Element::Vertex(Vertex::ResultSet),
};
assert_serde!(text, entry);
}
#[test]
fn contains() {
let text = r#"{ "id": 5, "type": "edge", "label": "contains", "outV": 1, "inVs": [4] }"#;
let entry = Entry {
id: Id::Number(5),
element: Element::Edge(Edge::Contains(E1N {
out_v: Id::Number(1),
in_vs: vec![Id::Number(4)],
})),
};
assert_serde!(text, entry);
}
#[test]
fn next() {
let text = r#"{ "id": 5, "type": "edge", "label": "next", "outV": 3, "inV": 2 }"#;
let entry = Entry {
id: Id::Number(5),
element: Element::Edge(Edge::Next(E11 {
out_v: Id::Number(3),
in_v: Id::Number(2),
})),
};
assert_serde!(text, entry);
}
#[test]
fn item() {
let text = r#"{ "id": 24, "type": "edge", "label": "item", "outV": 22, "inVs": [9], "document": 4 }"#;
let entry = Entry {
id: Id::Number(24),
element: Element::Edge(Edge::Item(Item {
out_v: Id::Number(22),
in_vs: vec![Id::Number(9)],
document: Id::Number(4),
property: None,
})),
};
assert_serde!(text, entry);
}
#[test]
fn item_property() {
let text = r#"{ "id": 90, "type": "edge", "label": "item", "outV": 30, "inVs": [16,34,50], "document": 4, "property": "definitions" }"#;
let entry = Entry {
id: Id::Number(90),
element: Element::Edge(Edge::Item(Item {
out_v: Id::Number(30),
in_vs: vec![Id::Number(16), Id::Number(34), Id::Number(50)],
document: Id::Number(4),
property: Some(ItemProperty::Definitions),
})),
};
assert_serde!(text, entry);
}
#[test]
fn definition_result() {
let text = r#"{ "id": 22, "type": "vertex", "label": "definitionResult" }"#;
let entry = Entry {
id: Id::Number(22),
element: Element::Vertex(Vertex::DefinitionResult),
};
assert_serde!(text, entry);
}
#[test]
fn definition() {
let text = r#"{ "id": 23, "type": "edge", "label": "textDocument/definition", "outV": 6, "inV": 22 }"#;
let entry = Entry {
id: Id::Number(23),
element: Element::Edge(Edge::Definition(E11 {
out_v: Id::Number(6),
in_v: Id::Number(22),
})),
};
assert_serde!(text, entry);
}
#[test]
fn hover_result() {
let text = r#"{ "id": 6, "type": "vertex", "label": "hoverResult", "result": { "contents": [ { "language": "typescript", "value": "function bar(): void" } ], "range": { "start": { "line": 4, "character": 2 }, "end": { "line": 4, "character": 5 } } } }"#;
let entry = Entry {
id: Id::Number(6),
element: Element::Vertex(Vertex::HoverResult {
result: lsp::Hover {
contents: HoverContents::Array(vec![MarkedString::LanguageString(
LanguageString {
language: "typescript".to_owned(),
value: "function bar(): void".to_owned(),
},
)]),
range: Some(lsp::Range {
start: Position {
line: 4,
character: 2,
},
end: Position {
line: 4,
character: 5,
},
}),
},
}),
};
assert_serde!(text, entry);
}
#[test]
fn hover() {
let text =
r#"{ "id": 7, "type": "edge", "label": "textDocument/hover", "outV": 4, "inV": 6 }"#;
let entry = Entry {
id: Id::Number(7),
element: Element::Edge(Edge::Hover(E11 {
out_v: Id::Number(4),
in_v: Id::Number(6),
})),
};
assert_serde!(text, entry);
}
#[test]
fn reference_result() {
let text = r#"{ "id": 25, "type": "vertex", "label": "referenceResult" }"#;
let entry = Entry {
id: Id::Number(25),
element: Element::Vertex(Vertex::ReferenceResult),
};
assert_serde!(text, entry);
}
#[test]
fn references() {
let text = r#"{ "id": 26, "type": "edge", "label": "textDocument/references", "outV": 6, "inV": 25 }"#;
let entry = Entry {
id: Id::Number(26),
element: Element::Edge(Edge::References(E11 {
out_v: Id::Number(6),
in_v: Id::Number(25),
})),
};
assert_serde!(text, entry);
}
#[test]
fn type_definition_result() {
let text = r#"{ "id" : 37, "type": "vertex", "label": "typeDefinitionResult" }"#;
let entry = Entry {
id: Id::Number(37),
element: Element::Vertex(Vertex::TypeDefinitionResult),
};
assert_serde!(text, entry);
}
#[test]
fn type_definition() {
let text = r#"{ "id": 38, "type": "edge", "label": "textDocument/typeDefinition", "outV": 26, "inV": 37 }"#;
let entry = Entry {
id: Id::Number(38),
element: Element::Edge(Edge::TypeDefinition(E11 {
out_v: Id::Number(26),
in_v: Id::Number(37),
})),
};
assert_serde!(text, entry);
}
#[test]
fn folding_range_result() {
let text = r#"{ "id": 112, "type": "vertex", "label": "foldingRangeResult", "result": [
{ "startLine": 0, "startCharacter": 16, "endLine": 2, "endCharacter": 1 },
{ "startLine": 4, "startCharacter": 16, "endLine": 6, "endCharacter": 1 },
{ "startLine": 8, "startCharacter": 16, "endLine": 10, "endCharacter": 1 }
]}"#;
let entry = Entry {
id: Id::Number(112),
element: Element::Vertex(Vertex::FoldingRangeResult {
result: vec![
lsp::FoldingRange {
start_line: 0,
start_character: Some(16),
end_line: 2,
end_character: Some(1),
kind: None,
},
lsp::FoldingRange {
start_line: 4,
start_character: Some(16),
end_line: 6,
end_character: Some(1),
kind: None,
},
lsp::FoldingRange {
start_line: 8,
start_character: Some(16),
end_line: 10,
end_character: Some(1),
kind: None,
},
],
}),
};
assert_serde!(text, entry);
}
#[test]
fn folding_range() {
let text = r#"{ "id": 113, "type": "edge", "label": "textDocument/foldingRange", "outV": 2, "inV": 112 }"#;
let entry = Entry {
id: Id::Number(113),
element: Element::Edge(Edge::FoldingRange(E11 {
out_v: Id::Number(2),
in_v: Id::Number(112),
})),
};
assert_serde!(text, entry);
}
#[test]
fn document_symbol_result() {
let text = r#"{ "id": 39, "type": "vertex", "label": "documentSymbolResult", "result": [ { "id": 7, "children": [ { "id": 18 }, { "id": 29 } ] } ] }"#;
let entry = Entry {
id: Id::Number(39),
element: Element::Vertex(Vertex::DocumentSymbolResult {
result: DocumentSymbolResult::RangeBasedDocumentSymbols(vec![
RangeBasedDocumentSymbol {
id: Id::Number(7),
children: Some(vec![
RangeBasedDocumentSymbol {
id: Id::Number(18),
children: None,
},
RangeBasedDocumentSymbol {
id: Id::Number(29),
children: None,
},
]),
},
]),
}),
};
assert_serde!(text, entry);
}
#[test]
fn document_symbol() {
let text = r#"{ "id": 40, "type": "edge", "label": "textDocument/documentSymbol", "outV": 2, "inV": 39 }"#;
let entry = Entry {
id: Id::Number(40),
element: Element::Edge(Edge::DocumentSymbol(E11 {
out_v: Id::Number(2),
in_v: Id::Number(39),
})),
};
assert_serde!(text, entry);
}
#[test]
fn diagnostic_result() {
let text = r#"{ "id": 18, "type": "vertex", "label": "diagnosticResult", "result": [ { "severity": 1, "code": 2322, "message": "Type '10' is not assignable to type 'string'.", "range": { "start": { "line": 1, "character": 5 }, "end": { "line": 1, "character": 6 } } } ] }"#;
let entry = Entry {
id: Id::Number(18),
element: Element::Vertex(Vertex::DiagnosticResult {
result: vec![lsp::Diagnostic {
range: lsp::Range {
start: lsp::Position {
line: 1,
character: 5,
},
end: lsp::Position {
line: 1,
character: 6,
},
},
severity: Some(lsp::DiagnosticSeverity::Error),
code: Some(Id::Number(2322)),
code_description: None,
source: None,
message: "Type '10' is not assignable to type 'string'.".to_owned(),
related_information: None,
tags: None,
data: None,
}],
}),
};
assert_serde!(text, entry);
}
#[test]
fn diagnostic() {
let text = r#"{ "id": 19, "type": "edge", "label": "textDocument/diagnostic", "outV": 2, "inV": 18 }"#;
let entry = Entry {
id: Id::Number(19),
element: Element::Edge(Edge::Diagnostic(E11 {
out_v: Id::Number(2),
in_v: Id::Number(18),
})),
};
assert_serde!(text, entry);
}
}