lsp_textdocument/
text_documents.rs

1use crate::FullTextDocument;
2use lsp_types::{
3    notification::{
4        DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, Notification,
5    },
6    DidChangeTextDocumentParams, DidCloseTextDocumentParams, DidOpenTextDocumentParams, Range, Uri,
7};
8use serde_json::Value;
9use std::collections::BTreeMap;
10
11#[derive(Default)]
12pub struct TextDocuments(BTreeMap<Uri, FullTextDocument>);
13
14impl TextDocuments {
15    /// Create a text documents
16    ///
17    /// # Examples
18    ///
19    /// Basic usage:
20    ///
21    /// ```
22    /// use lsp_textdocument::TextDocuments;
23    ///
24    /// let text_documents = TextDocuments::new();
25    /// ```
26    pub fn new() -> Self {
27        Self(BTreeMap::new())
28    }
29
30    pub fn documents(&self) -> &BTreeMap<Uri, FullTextDocument> {
31        &self.0
32    }
33
34    /// Get specify document by giving Uri
35    ///
36    /// # Examples:
37    ///
38    /// Basic usage:
39    /// ```
40    /// use lsp_textdocument::TextDocuments;
41    /// use lsp_types::Uri;
42    ///
43    /// let text_documents = TextDocuments::new();
44    /// let uri:Uri = "file://example.txt".parse().unwrap();
45    /// text_documents.get_document(&uri);
46    /// ```
47    pub fn get_document(&self, uri: &Uri) -> Option<&FullTextDocument> {
48        self.0.get(uri)
49    }
50
51    /// Get specify document content by giving Range
52    ///
53    /// # Examples
54    ///
55    /// Basic usage:
56    /// ```no_run
57    /// use lsp_textdocument::TextDocuments;
58    /// use lsp_types::{Uri, Range, Position};
59    ///
60    /// let uri: Uri = "file://example.txt".parse().unwrap();
61    /// let text_documents = TextDocuments::new();
62    ///
63    /// // get document all content
64    /// let content = text_documents.get_document_content(&uri, None);
65    /// assert_eq!(content, Some("hello rust!"));
66    ///
67    /// // get document specify content by range
68    /// let (start, end) = (Position::new(0, 1), Position::new(0, 9));
69    /// let range = Range::new(start, end);
70    /// let sub_content = text_documents.get_document_content(&uri, Some(range));
71    /// assert_eq!(sub_content, Some("ello rus"));
72    /// ```
73    pub fn get_document_content(&self, uri: &Uri, range: Option<Range>) -> Option<&str> {
74        self.0.get(uri).map(|document| document.get_content(range))
75    }
76
77    /// Get specify document's language by giving Uri
78    ///
79    /// # Examples
80    ///
81    /// Basic usage:
82    /// ```no_run
83    /// use lsp_textdocument::TextDocuments;
84    /// use lsp_types::Uri;
85    ///
86    /// let text_documents = TextDocuments::new();
87    /// let uri:Uri = "file://example.js".parse().unwrap();
88    /// let language =  text_documents.get_document_language(&uri);
89    /// assert_eq!(language, Some("javascript"));
90    /// ```
91    pub fn get_document_language(&self, uri: &Uri) -> Option<&str> {
92        self.0.get(uri).map(|document| document.language_id())
93    }
94
95    /// Listening the notification from client, you just need to pass `method` and `params`
96    ///
97    /// # Examples:
98    ///
99    /// Basic usage:
100    /// ```no_run
101    /// use lsp_textdocument::TextDocuments;
102    ///
103    /// let method = "textDocument/didOpen";
104    /// let params = serde_json::to_value("message produced by client").unwrap();
105    ///
106    /// let mut text_documents = TextDocuments::new();
107    /// let accept: bool = text_documents.listen(method, &params);
108    /// ```
109    pub fn listen(&mut self, method: &str, params: &Value) -> bool {
110        match method {
111            DidOpenTextDocument::METHOD => {
112                let params: DidOpenTextDocumentParams = serde_json::from_value(params.clone())
113                    .expect("Expect receive DidOpenTextDocumentParams");
114                let text_document = params.text_document;
115
116                let document = FullTextDocument::new(
117                    text_document.language_id,
118                    text_document.version,
119                    text_document.text,
120                );
121                self.0.insert(text_document.uri, document);
122                true
123            }
124            DidChangeTextDocument::METHOD => {
125                let params: DidChangeTextDocumentParams = serde_json::from_value(params.clone())
126                    .expect("Expect receive DidChangeTextDocumentParams");
127
128                if let Some(document) = self.0.get_mut(&params.text_document.uri) {
129                    let changes = &params.content_changes;
130                    let version = params.text_document.version;
131                    document.update(changes, version);
132                };
133                true
134            }
135            DidCloseTextDocument::METHOD => {
136                let params: DidCloseTextDocumentParams = serde_json::from_value(params.clone())
137                    .expect("Expect receive DidCloseTextDocumentParams");
138
139                self.0.remove(&params.text_document.uri);
140                true
141            }
142            _ => {
143                // ignore other request
144                false
145            }
146        }
147    }
148}