|
1 | | -use std::collections::HashMap; |
2 | | - |
3 | | -use anyhow::anyhow; |
4 | | -use anyhow::Result; |
5 | | -use djls_project::TemplateTags; |
6 | 1 | use salsa::Database; |
7 | | -use tower_lsp_server::lsp_types::CompletionItem; |
8 | | -use tower_lsp_server::lsp_types::CompletionItemKind; |
9 | | -use tower_lsp_server::lsp_types::CompletionResponse; |
10 | | -use tower_lsp_server::lsp_types::DidChangeTextDocumentParams; |
11 | | -use tower_lsp_server::lsp_types::DidCloseTextDocumentParams; |
12 | 2 | use tower_lsp_server::lsp_types::DidOpenTextDocumentParams; |
13 | | -use tower_lsp_server::lsp_types::Documentation; |
14 | | -use tower_lsp_server::lsp_types::InsertTextFormat; |
15 | | -use tower_lsp_server::lsp_types::MarkupContent; |
16 | | -use tower_lsp_server::lsp_types::MarkupKind; |
17 | 3 | use tower_lsp_server::lsp_types::Position; |
18 | 4 | use tower_lsp_server::lsp_types::Range; |
19 | 5 | use tower_lsp_server::lsp_types::TextDocumentContentChangeEvent; |
20 | 6 |
|
21 | | -#[derive(Debug, Default)] |
22 | | -pub struct Store { |
23 | | - documents: HashMap<String, TextDocument>, |
24 | | - versions: HashMap<String, i32>, |
25 | | -} |
26 | | - |
27 | | -impl Store { |
28 | | - pub fn handle_did_open(&mut self, db: &dyn Database, params: &DidOpenTextDocumentParams) { |
29 | | - let uri = params.text_document.uri.to_string(); |
30 | | - let version = params.text_document.version; |
31 | | - |
32 | | - let document = TextDocument::from_did_open_params(db, params); |
33 | | - |
34 | | - self.add_document(document, uri.clone()); |
35 | | - self.versions.insert(uri, version); |
36 | | - } |
37 | | - |
38 | | - pub fn handle_did_change( |
39 | | - &mut self, |
40 | | - db: &dyn Database, |
41 | | - params: &DidChangeTextDocumentParams, |
42 | | - ) -> Result<()> { |
43 | | - let uri = params.text_document.uri.as_str().to_string(); |
44 | | - let version = params.text_document.version; |
45 | | - |
46 | | - let document = self |
47 | | - .get_document(&uri) |
48 | | - .ok_or_else(|| anyhow!("Document not found: {}", uri))?; |
49 | | - |
50 | | - let new_document = document.with_changes(db, ¶ms.content_changes, version); |
51 | | - |
52 | | - self.documents.insert(uri.clone(), new_document); |
53 | | - self.versions.insert(uri, version); |
54 | | - |
55 | | - Ok(()) |
56 | | - } |
57 | | - |
58 | | - pub fn handle_did_close(&mut self, params: &DidCloseTextDocumentParams) { |
59 | | - self.remove_document(params.text_document.uri.as_str()); |
60 | | - } |
61 | | - |
62 | | - fn add_document(&mut self, document: TextDocument, uri: String) { |
63 | | - self.documents.insert(uri, document); |
64 | | - } |
65 | | - |
66 | | - fn remove_document(&mut self, uri: &str) { |
67 | | - self.documents.remove(uri); |
68 | | - self.versions.remove(uri); |
69 | | - } |
70 | | - |
71 | | - fn get_document(&self, uri: &str) -> Option<&TextDocument> { |
72 | | - self.documents.get(uri) |
73 | | - } |
74 | | - |
75 | | - #[allow(dead_code)] |
76 | | - fn get_document_mut(&mut self, uri: &str) -> Option<&mut TextDocument> { |
77 | | - self.documents.get_mut(uri) |
78 | | - } |
79 | | - |
80 | | - #[allow(dead_code)] |
81 | | - pub fn get_all_documents(&self) -> impl Iterator<Item = &TextDocument> { |
82 | | - self.documents.values() |
83 | | - } |
84 | | - |
85 | | - #[allow(dead_code)] |
86 | | - pub fn get_documents_by_language<'db>( |
87 | | - &'db self, |
88 | | - db: &'db dyn Database, |
89 | | - language_id: LanguageId, |
90 | | - ) -> impl Iterator<Item = &'db TextDocument> + 'db { |
91 | | - self.documents |
92 | | - .values() |
93 | | - .filter(move |doc| doc.language_id(db) == language_id) |
94 | | - } |
95 | | - |
96 | | - #[allow(dead_code)] |
97 | | - pub fn get_version(&self, uri: &str) -> Option<i32> { |
98 | | - self.versions.get(uri).copied() |
99 | | - } |
100 | | - |
101 | | - #[allow(dead_code)] |
102 | | - pub fn is_version_valid(&self, uri: &str, version: i32) -> bool { |
103 | | - self.get_version(uri) == Some(version) |
104 | | - } |
105 | | - |
106 | | - pub fn get_completions( |
107 | | - &self, |
108 | | - db: &dyn Database, |
109 | | - uri: &str, |
110 | | - position: Position, |
111 | | - tags: &TemplateTags, |
112 | | - ) -> Option<CompletionResponse> { |
113 | | - let document = self.get_document(uri)?; |
114 | | - |
115 | | - if document.language_id(db) != LanguageId::HtmlDjango { |
116 | | - return None; |
117 | | - } |
118 | | - |
119 | | - let context = document.get_template_tag_context(db, position)?; |
120 | | - |
121 | | - let mut completions: Vec<CompletionItem> = tags |
122 | | - .iter() |
123 | | - .filter(|tag| { |
124 | | - context.partial_tag.is_empty() || tag.name().starts_with(&context.partial_tag) |
125 | | - }) |
126 | | - .map(|tag| { |
127 | | - let leading_space = if context.needs_leading_space { " " } else { "" }; |
128 | | - CompletionItem { |
129 | | - label: tag.name().to_string(), |
130 | | - kind: Some(CompletionItemKind::KEYWORD), |
131 | | - detail: Some(format!("Template tag from {}", tag.library())), |
132 | | - documentation: tag.doc().as_ref().map(|doc| { |
133 | | - Documentation::MarkupContent(MarkupContent { |
134 | | - kind: MarkupKind::Markdown, |
135 | | - value: (*doc).to_string(), |
136 | | - }) |
137 | | - }), |
138 | | - insert_text: Some(match context.closing_brace { |
139 | | - ClosingBrace::None => format!("{}{} %}}", leading_space, tag.name()), |
140 | | - ClosingBrace::PartialClose => format!("{}{} %", leading_space, tag.name()), |
141 | | - ClosingBrace::FullClose => format!("{}{} ", leading_space, tag.name()), |
142 | | - }), |
143 | | - insert_text_format: Some(InsertTextFormat::PLAIN_TEXT), |
144 | | - ..Default::default() |
145 | | - } |
146 | | - }) |
147 | | - .collect(); |
148 | | - |
149 | | - if completions.is_empty() { |
150 | | - None |
151 | | - } else { |
152 | | - completions.sort_by(|a, b| a.label.cmp(&b.label)); |
153 | | - Some(CompletionResponse::Array(completions)) |
154 | | - } |
155 | | - } |
156 | | -} |
157 | | - |
158 | 7 | #[salsa::input(debug)] |
159 | 8 | pub struct TextDocument { |
160 | 9 | #[returns(ref)] |
161 | | - uri: String, |
| 10 | + pub uri: String, |
162 | 11 | #[returns(ref)] |
163 | | - contents: String, |
| 12 | + pub contents: String, |
164 | 13 | #[returns(ref)] |
165 | | - index: LineIndex, |
166 | | - version: i32, |
167 | | - language_id: LanguageId, |
| 14 | + pub index: LineIndex, |
| 15 | + pub version: i32, |
| 16 | + pub language_id: LanguageId, |
168 | 17 | } |
169 | 18 |
|
170 | 19 | impl TextDocument { |
|
0 commit comments