mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-06 18:30:35 +00:00
migrate all async tokio to server & swap to single-thread runtime (#149)
This commit is contained in:
parent
c29b268326
commit
def9fba2b6
12 changed files with 45 additions and 103 deletions
|
@ -17,10 +17,10 @@ pyo3 = { workspace = true }
|
|||
salsa = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tower-lsp-server = { workspace = true }
|
||||
|
||||
percent-encoding = "2.3"
|
||||
percent-encoding = "2.3.1"
|
||||
tokio = { version = "1.45.0", features = ["full"] }
|
||||
tower-lsp-server = { version = "0.21.1", features = ["proposed"] }
|
||||
|
||||
[build-dependencies]
|
||||
djls-dev = { workspace = true }
|
||||
|
|
|
@ -25,13 +25,6 @@ pub struct Store {
|
|||
}
|
||||
|
||||
impl Store {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
documents: HashMap::new(),
|
||||
versions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_did_open(&mut self, db: &dyn Database, params: &DidOpenTextDocumentParams) {
|
||||
let uri = params.text_document.uri.to_string();
|
||||
let version = params.text_document.version;
|
||||
|
|
|
@ -5,4 +5,25 @@ mod server;
|
|||
mod session;
|
||||
mod workspace;
|
||||
|
||||
pub use crate::server::DjangoLanguageServer;
|
||||
use anyhow::Result;
|
||||
use tower_lsp_server::LspService;
|
||||
use tower_lsp_server::Server;
|
||||
|
||||
use crate::server::DjangoLanguageServer;
|
||||
|
||||
pub fn run() -> Result<()> {
|
||||
let runtime = tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()?;
|
||||
|
||||
runtime.block_on(async {
|
||||
let stdin = tokio::io::stdin();
|
||||
let stdout = tokio::io::stdout();
|
||||
|
||||
let (service, socket) = LspService::build(DjangoLanguageServer::new).finish();
|
||||
|
||||
Server::new(stdin, stdout, socket).serve(service).await;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,7 +19,9 @@ use tokio::sync::oneshot;
|
|||
/// required for self-referential `async` blocks.
|
||||
/// - `Box`: Allocates the `Future` on the heap.
|
||||
/// - `dyn Future`: Type erasure - hides the specific concrete `Future` type.
|
||||
/// - `+ Send`: Ensures the `Future` can be safely sent across threads.
|
||||
/// - `+ Send`: Ensures the `Future` can be safely sent across threads and required
|
||||
/// by the tower-lsp-server LSP server trait bounds, even in our single-threaded
|
||||
/// runtime.
|
||||
type TaskFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
|
||||
|
||||
/// Type alias for a type-erased, heap-allocated, Send-able closure that,
|
||||
|
@ -34,7 +36,8 @@ type TaskFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
|
|||
/// arguments.
|
||||
/// - `-> TaskFuture`: Specifies that calling the closure produces the type-erased future.
|
||||
/// - `+ Send + 'static`: Ensures the closure itself can be safely sent across
|
||||
/// threads and has a static lifetime (doesn't borrow short-lived data).
|
||||
/// threads and has a static lifetime (doesn't borrow short-lived data). Required
|
||||
/// for compatibility with our async runtime and LSP traits.
|
||||
type TaskClosure = Box<dyn FnOnce() -> TaskFuture + Send + 'static>;
|
||||
|
||||
/// A simple asynchronous task queue for sequential execution.
|
||||
|
@ -43,8 +46,9 @@ type TaskClosure = Box<dyn FnOnce() -> TaskFuture + Send + 'static>;
|
|||
/// to a dedicated worker task which executes them one at a time in the order
|
||||
/// they were received. This ensures sequential processing of background tasks.
|
||||
///
|
||||
/// The queue is cloneable (`Arc`-based internally), allowing multiple producers
|
||||
/// to submit tasks concurrently.
|
||||
/// The queue runs within our single-threaded runtime but maintains compatibility
|
||||
/// with the Send+Sync requirements of the LSP. This provides the benefits of
|
||||
/// simpler execution while maintaining the required trait bounds.
|
||||
///
|
||||
/// Shutdown is handled gracefully when the last `Queue` instance is dropped.
|
||||
#[derive(Clone)]
|
||||
|
|
|
@ -19,6 +19,10 @@ pub struct Session {
|
|||
/// where we're using the `StorageHandle` to create a thread-safe handle that can be
|
||||
/// shared between threads. When we need to use it, we clone the handle to get a new reference.
|
||||
///
|
||||
/// This handle allows us to create database instances as needed.
|
||||
/// Even though we're using a single-threaded runtime, we still need
|
||||
/// this to be thread-safe because of LSP trait requirements.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```rust,ignore
|
||||
/// // Use the StorageHandle in Session
|
||||
|
@ -41,20 +45,6 @@ pub struct Session {
|
|||
}
|
||||
|
||||
impl Session {
|
||||
pub fn new(client_capabilities: ClientCapabilities) -> Self {
|
||||
Self {
|
||||
client_capabilities: Some(client_capabilities),
|
||||
project: None,
|
||||
documents: Store::new(),
|
||||
settings: Settings::default(),
|
||||
db_handle: StorageHandle::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client_capabilities(&self) -> Option<&ClientCapabilities> {
|
||||
self.client_capabilities.as_ref()
|
||||
}
|
||||
|
||||
pub fn client_capabilities_mut(&mut self) -> &mut Option<ClientCapabilities> {
|
||||
&mut self.client_capabilities
|
||||
}
|
||||
|
@ -83,14 +73,6 @@ impl Session {
|
|||
&mut self.settings
|
||||
}
|
||||
|
||||
/// Get the raw database handle from the session
|
||||
///
|
||||
/// Note: In most cases, you'll want to use `db()` instead to get a usable
|
||||
/// database instance directly.
|
||||
pub fn db_handle(&self) -> &StorageHandle<ServerDatabase> {
|
||||
&self.db_handle
|
||||
}
|
||||
|
||||
/// Get a database instance directly from the session
|
||||
///
|
||||
/// This creates a usable database from the handle, which can be used
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue