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, ¶ms);
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(¶ms.text_document.uri) {
129 let changes = ¶ms.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(¶ms.text_document.uri);
140 true
141 }
142 _ => {
143 // ignore other request
144 false
145 }
146 }
147 }
148}