django-language-server/crates/djls-server/src/lib.rs
Josh 2dd779bcda Fix overlay bug: Salsa wasn't re-reading from buffers when files were opened
The core issue was that when a file was opened in the LSP, if it had already
been read from disk, Salsa would return cached content instead of reading
from the overlay system. This happened because opening a file didn't bump
its revision, so Salsa had no reason to invalidate its cache.

Key changes:
- Created Buffers abstraction to encapsulate shared buffer storage
- Fixed Session::open_document() to bump revision when file already exists
- Added comprehensive integration tests to verify overlay behavior
- Refactored WorkspaceFileSystem to use Buffers instead of raw DashMap

This ensures that overlays always take precedence over disk content, fixing
the issue where LSP edits weren't being reflected in template parsing.
2025-08-29 07:55:37 -05:00

62 lines
1.9 KiB
Rust

mod client;
mod logging;
mod queue;
pub mod server;
pub mod session;
use std::io::IsTerminal;
use anyhow::Result;
use tower_lsp_server::LspService;
use tower_lsp_server::Server;
pub use crate::server::DjangoLanguageServer;
pub use crate::session::Session;
pub fn run() -> Result<()> {
if std::io::stdin().is_terminal() {
eprintln!(
"---------------------------------------------------------------------------------"
);
eprintln!("Django Language Server is running directly in a terminal.");
eprintln!(
"This server is designed to communicate over stdin/stdout with a language client."
);
eprintln!("It is not intended to be used directly in a terminal.");
eprintln!();
eprintln!(
"Note: The server is now waiting for LSP messages, but since you're in a terminal,"
);
eprintln!("no editor is connected and the server won't do anything.");
eprintln!();
eprintln!("To exit: Press ENTER to send invalid input and trigger an error exit.");
eprintln!("Ctrl+C will not work as expected due to LSP stdio communication.");
eprintln!(
"---------------------------------------------------------------------------------"
);
}
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(|client| {
client::init_client(client);
let log_guard = logging::init_tracing(|message_type, message| {
client::log_message(message_type, message);
});
DjangoLanguageServer::new(log_guard)
})
.finish();
Server::new(stdin, stdout, socket).serve(service).await;
Ok(())
})
}