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