Skip to content

Commit 2086f80

Browse files
reorganize server crate by moving workspace related code to submodule (#182)
1 parent d0c745f commit 2086f80

File tree

6 files changed

+170
-158
lines changed

6 files changed

+170
-158
lines changed

crates/djls-server/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
mod client;
22
mod db;
3-
mod documents;
43
mod logging;
54
mod queue;
65
mod server;

crates/djls-server/src/session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use tower_lsp_server::lsp_types::ClientCapabilities;
55
use tower_lsp_server::lsp_types::InitializeParams;
66

77
use crate::db::ServerDatabase;
8-
use crate::documents::Store;
8+
use crate::workspace::Store;
99

1010
#[derive(Default)]
1111
pub struct Session {

crates/djls-server/src/documents.rs renamed to crates/djls-server/src/workspace/document.rs

Lines changed: 5 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,19 @@
1-
use std::collections::HashMap;
2-
3-
use anyhow::anyhow;
4-
use anyhow::Result;
5-
use djls_project::TemplateTags;
61
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;
122
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;
173
use tower_lsp_server::lsp_types::Position;
184
use tower_lsp_server::lsp_types::Range;
195
use tower_lsp_server::lsp_types::TextDocumentContentChangeEvent;
206

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, &params.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-
1587
#[salsa::input(debug)]
1598
pub struct TextDocument {
1609
#[returns(ref)]
161-
uri: String,
10+
pub uri: String,
16211
#[returns(ref)]
163-
contents: String,
12+
pub contents: String,
16413
#[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,
16817
}
16918

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

0 commit comments

Comments
 (0)