From 2a693bfa95cc182bbf44cd06383db617de06b84a Mon Sep 17 00:00:00 2001 From: Junfeng Li Date: Sun, 31 Dec 2017 18:38:19 -0800 Subject: [PATCH] Make WorkspaceEdit compatible with protocol 3.0. Note: the SerdeUrl/Serde can be replaced by Url once https://github.com/servo/rust-url/issues/304 is merged in. --- src/lib.rs | 106 ++++++++++++++++++++++------------------------------- 1 file changed, 43 insertions(+), 63 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 36bb367..0fb2833 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -264,73 +264,51 @@ impl TextEdit { } } +/** + Describes textual changes on a single text document. The text document is referred to as a + `VersionedTextDocumentIdentifier` to allow clients to check the text document version before an + edit is applied. A `TextDocumentEdit` describes all changes on a version Si and after they are + applied move the document to version Si+1. So the creator of a `TextDocumentEdit` doesn't need to + sort the array or do any kind of ordering. However the edits must be non overlapping. + */ +#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)] +pub struct TextDocumentEdit { + /** + * The text document to change. + */ + #[serde(rename = "textDocument")] + pub text_document: VersionedTextDocumentIdentifier, + + /** + * The edits to be applied. + */ + pub edits: Vec, +} + /// A workspace edit represents changes to many resources managed in the workspace. #[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)] pub struct WorkspaceEdit { /// Holds changes to existing resources. - #[serde(with = "url_map")] - pub changes: HashMap>, // changes: { [uri: string]: TextEdit[]; }; -} - -mod url_map { - use super::*; - - use std::fmt; - - pub fn deserialize<'de, D>(deserializer: D) -> Result>, D::Error> - where - D: serde::Deserializer<'de>, - { - struct UrlMapVisitor; - - impl<'de> de::Visitor<'de> for UrlMapVisitor { - type Value = HashMap>; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("map") - } - - fn visit_map(self, mut visitor: M) -> Result - where - M: de::MapAccess<'de>, - { - let mut values = HashMap::with_capacity(visitor.size_hint().unwrap_or(0)); - - // While there are entries remaining in the input, add them - // into our map. - while let Some((key, value)) = visitor.next_entry::, _>()? { - values.insert(key.into_inner(), value); - } - - Ok(values) - } - } - - // Instantiate our Visitor and ask the Deserializer to drive - // it over the input data, resulting in an instance of MyMap. - deserializer.deserialize_map(UrlMapVisitor) - } - - pub fn serialize( - changes: &HashMap>, - serializer: S, - ) -> Result - where - S: serde::Serializer, - { - use serde::ser::SerializeMap; + pub changes: Option>>, - let mut map = serializer.serialize_map(Some(changes.len()))?; - for (k, v) in changes { - map.serialize_entry(k.as_str(), v)?; - } - map.end() - } + /** + * An array of `TextDocumentEdit`s to express changes to n different text documents + * where each text document edit addresses a specific version of a text document. + * Whether a client supports versioned document edits is expressed via + * `WorkspaceClientCapabilities.workspaceEdit.documentChanges`. + */ + #[serde(rename = "documentChanges")] + pub document_changes: Option>, } impl WorkspaceEdit { pub fn new(changes: HashMap>) -> WorkspaceEdit { - WorkspaceEdit { changes: changes } + let mut map = HashMap::new(); + for (k, v) in changes { + map.insert(url_serde::Serde(k), v); + } + + WorkspaceEdit { changes: Some(map), document_changes: None, } } } @@ -2303,17 +2281,19 @@ mod tests { fn workspace_edit() { test_serialization( &WorkspaceEdit { - changes: vec![].into_iter().collect(), + changes: Some(vec![].into_iter().collect()), + document_changes: None, }, - r#"{"changes":{}}"#, + r#"{"changes":{},"documentChanges":null}"#, ); test_serialization(&WorkspaceEdit { - changes: vec![(Url::parse("file://test").unwrap(), vec![])] + changes: Some(vec![(url_serde::Serde(Url::parse("file://test").unwrap()), vec![])] .into_iter() - .collect(), + .collect()), + document_changes: None, }, - r#"{"changes":{"file://test/":[]}}"#); + r#"{"changes":{"file://test/":[]},"documentChanges":null}"#); } #[test]