Skip to content

Commit ae1f8d3

Browse files
refactor and establish better boundaries in doc lifecycle (#285)
1 parent 40c7661 commit ae1f8d3

File tree

8 files changed

+275
-503
lines changed

8 files changed

+275
-503
lines changed

crates/djls-server/src/ext.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,30 +60,6 @@ impl TextDocumentIdentifierExt for lsp_types::TextDocumentIdentifier {
6060
}
6161
}
6262

63-
pub(crate) trait TextDocumentItemExt {
64-
/// Convert LSP `TextDocumentItem` to internal `TextDocument`
65-
fn into_text_document(
66-
self,
67-
db: &mut dyn djls_source::Db,
68-
) -> Option<djls_workspace::TextDocument>;
69-
}
70-
71-
impl TextDocumentItemExt for lsp_types::TextDocumentItem {
72-
fn into_text_document(
73-
self,
74-
db: &mut dyn djls_source::Db,
75-
) -> Option<djls_workspace::TextDocument> {
76-
let path = self.uri.to_utf8_path_buf()?;
77-
Some(djls_workspace::TextDocument::new(
78-
self.text,
79-
self.version,
80-
djls_workspace::LanguageId::from(self.language_id.as_str()),
81-
&path,
82-
db,
83-
))
84-
}
85-
}
86-
8763
pub(crate) trait UriExt {
8864
/// Convert `Utf8Path` to LSP Uri
8965
fn from_path(path: &Utf8Path) -> Option<Self>

crates/djls-server/src/server.rs

Lines changed: 29 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::future::Future;
22
use std::sync::Arc;
33

4-
use camino::Utf8Path;
54
use djls_project::Db as ProjectDb;
65
use djls_semantic::Db as SemanticDb;
76
use djls_source::Db as SourceDb;
87
use djls_source::FileKind;
8+
use djls_workspace::TextDocument;
99
use tokio::sync::Mutex;
1010
use tower_lsp_server::jsonrpc::Result as LspResult;
1111
use tower_lsp_server::lsp_types;
@@ -16,7 +16,6 @@ use tracing_appender::non_blocking::WorkerGuard;
1616
use crate::ext::PositionEncodingExt;
1717
use crate::ext::PositionExt;
1818
use crate::ext::TextDocumentIdentifierExt;
19-
use crate::ext::TextDocumentItemExt;
2019
use crate::ext::UriExt;
2120
use crate::queue::Queue;
2221
use crate::session::Session;
@@ -72,36 +71,37 @@ impl DjangoLanguageServer {
7271
}
7372
}
7473

75-
async fn publish_diagnostics(&self, path: &Utf8Path, version: Option<i32>) {
74+
async fn publish_diagnostics(&self, document: &TextDocument) {
7675
let supports_pull = self
7776
.with_session(super::session::Session::supports_pull_diagnostics)
7877
.await;
7978

8079
if supports_pull {
81-
tracing::debug!(
82-
"Client supports pull diagnostics, skipping push for {}",
83-
path
84-
);
80+
tracing::debug!("Client supports pull diagnostics, skipping push");
8581
return;
8682
}
8783

88-
if FileKind::from(path) != FileKind::Template {
84+
let path = self
85+
.with_session(|session| session.with_db(|db| document.file().path(db).to_owned()))
86+
.await;
87+
88+
if FileKind::from(&path) != FileKind::Template {
8989
return;
9090
}
9191

9292
let diagnostics: Vec<lsp_types::Diagnostic> = self
9393
.with_session_mut(|session| {
9494
session.with_db(|db| {
95-
let file = db.get_or_create_file(path);
95+
let file = db.get_or_create_file(&path);
9696
let nodelist = djls_templates::parse_template(db, file);
9797
djls_ide::collect_diagnostics(db, file, nodelist)
9898
})
9999
})
100100
.await;
101101

102-
if let Some(lsp_uri) = lsp_types::Uri::from_path(path) {
102+
if let Some(lsp_uri) = lsp_types::Uri::from_path(&path) {
103103
self.client
104-
.publish_diagnostics(lsp_uri, diagnostics.clone(), version)
104+
.publish_diagnostics(lsp_uri, diagnostics.clone(), Some(document.version()))
105105
.await;
106106

107107
tracing::debug!("Published {} diagnostics for {}", diagnostics.len(), path);
@@ -197,92 +197,40 @@ impl LanguageServer for DjangoLanguageServer {
197197
}
198198

199199
async fn did_open(&self, params: lsp_types::DidOpenTextDocumentParams) {
200-
tracing::info!("Opened document: {:?}", params.text_document.uri);
201-
202-
let path_version = self
203-
.with_session_mut(|session| {
204-
let Some(path) = params.text_document.uri.to_utf8_path_buf() else {
205-
tracing::debug!(
206-
"Skipping non-file URI in did_open: {}",
207-
params.text_document.uri.as_str()
208-
);
209-
// TODO(virtual-paths): Support virtual documents with DocumentPath enum
210-
return None;
211-
};
212-
let document =
213-
session.with_db_mut(|db| params.text_document.into_text_document(db))?;
214-
let version = document.version();
215-
216-
session.open_document(&path, document);
217-
218-
Some((path, version))
219-
})
200+
let document = self
201+
.with_session_mut(|session| session.open_document(&params.text_document))
220202
.await;
221203

222-
if let Some((path, version)) = path_version {
223-
self.publish_diagnostics(&path, Some(version)).await;
204+
if let Some(document) = document {
205+
self.publish_diagnostics(&document).await;
224206
}
225207
}
226208

227209
async fn did_save(&self, params: lsp_types::DidSaveTextDocumentParams) {
228-
tracing::info!("Saved document: {:?}", params.text_document.uri);
229-
230-
let path_version = self
231-
.with_session_mut(|session| {
232-
let Some(path) = params.text_document.uri.to_utf8_path_buf() else {
233-
tracing::debug!(
234-
"Skipping non-file URI in did_save: {}",
235-
params.text_document.uri.as_str()
236-
);
237-
// TODO(virtual-paths): Support virtual documents with DocumentPath enum
238-
return None;
239-
};
240-
let version = session.save_document(&path).map(|doc| doc.version());
241-
Some((path, version))
242-
})
210+
let document = self
211+
.with_session_mut(|session| session.save_document(&params.text_document))
243212
.await;
244213

245-
if let Some((path, version)) = path_version {
246-
self.publish_diagnostics(&path, version).await;
214+
if let Some(document) = document {
215+
self.publish_diagnostics(&document).await;
247216
}
248217
}
249218

250219
async fn did_change(&self, params: lsp_types::DidChangeTextDocumentParams) {
251-
tracing::info!("Changed document: {:?}", params.text_document.uri);
220+
let document = self
221+
.with_session_mut(|session| {
222+
session.update_document(&params.text_document, params.content_changes)
223+
})
224+
.await;
252225

253-
self.with_session_mut(|session| {
254-
let Some(path) = params.text_document.uri.to_utf8_path_buf() else {
255-
tracing::debug!(
256-
"Skipping non-file URI in did_change: {}",
257-
params.text_document.uri.as_str()
258-
);
259-
// TODO(virtual-paths): Support virtual documents with DocumentPath enum
260-
return None;
261-
};
262-
session.update_document(&path, params.content_changes, params.text_document.version);
263-
Some(path)
264-
})
265-
.await;
226+
if let Some(document) = document {
227+
self.publish_diagnostics(&document).await;
228+
}
266229
}
267230

268231
async fn did_close(&self, params: lsp_types::DidCloseTextDocumentParams) {
269-
tracing::info!("Closed document: {:?}", params.text_document.uri);
270-
271-
self.with_session_mut(|session| {
272-
let Some(path) = params.text_document.uri.to_utf8_path_buf() else {
273-
tracing::debug!(
274-
"Skipping non-file URI in did_close: {}",
275-
params.text_document.uri.as_str()
276-
);
277-
// TODO(virtual-paths): Support virtual documents with DocumentPath enum
278-
return None;
279-
};
280-
if session.close_document(&path).is_none() {
281-
tracing::warn!("Attempted to close document without overlay: {}", path);
282-
}
283-
Some(path)
284-
})
285-
.await;
232+
self.with_session_mut(|session| session.close_document(&params.text_document))
233+
.await;
286234
}
287235

288236
async fn completion(

0 commit comments

Comments
 (0)