mirror of
https://github.com/joshuadavidthomas/django-language-server.git
synced 2025-09-10 12:26:50 +00:00
Move client handling from server to global static (#153)
This commit is contained in:
parent
460c1ce0a1
commit
9e13422245
3 changed files with 310 additions and 97 deletions
241
crates/djls-server/src/client.rs
Normal file
241
crates/djls-server/src/client.rs
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
pub use messages::*;
|
||||||
|
use tower_lsp_server::jsonrpc::Error;
|
||||||
|
use tower_lsp_server::Client;
|
||||||
|
|
||||||
|
static CLIENT: OnceLock<Arc<Client>> = OnceLock::new();
|
||||||
|
|
||||||
|
pub fn init_client(client: Client) {
|
||||||
|
let client_arc = Arc::new(client);
|
||||||
|
CLIENT
|
||||||
|
.set(client_arc)
|
||||||
|
.expect("client should only be initialized once");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_client() -> Option<Arc<Client>> {
|
||||||
|
CLIENT.get().cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a fire-and-forget notification function that spawns an async task.
|
||||||
|
///
|
||||||
|
/// This macro creates a wrapper function that:
|
||||||
|
/// 1. Gets the global client instance
|
||||||
|
/// 2. Spawns a new Tokio task that calls the client method asynchronously
|
||||||
|
/// 3. Does not wait for completion or handle errors
|
||||||
|
///
|
||||||
|
/// This...
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// notify!(log_message, message_type: MessageType, message: impl Display + Send + 'static);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ...expands to:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// pub fn log_message(message_type: MessageType, message: impl Display + Send + 'static) {
|
||||||
|
/// if let Some(client) = get_client() {
|
||||||
|
/// tokio::spawn(async move {
|
||||||
|
/// client.log_message(message_type, message).await;
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
macro_rules! notify {
|
||||||
|
($name:ident, $($param:ident: $type:ty),*) => {
|
||||||
|
pub fn $name($($param: $type),*) {
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
client.$name($($param),*).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates a fire-and-forget notification function that spawns an async task and discards any errors.
|
||||||
|
///
|
||||||
|
/// Similar to `notify!`, but explicitly discards any errors returned by the client method.
|
||||||
|
/// This is useful for methods that might return a Result but where you don't care about the outcome.
|
||||||
|
///
|
||||||
|
/// This...
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// notify_discard!(code_lens_refresh,);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ...expands to:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// pub fn code_lens_refresh() {
|
||||||
|
/// if let Some(client) = get_client() {
|
||||||
|
/// tokio::spawn(async move {
|
||||||
|
/// let _ = client.code_lens_refresh().await;
|
||||||
|
/// });
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
macro_rules! notify_discard {
|
||||||
|
($name:ident, $($param:ident: $type:ty),*) => {
|
||||||
|
pub fn $name($($param: $type),*) {
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = client.$name($($param),*).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generates an async request function that awaits a response from the client.
|
||||||
|
///
|
||||||
|
/// Unlike the notification macros, this creates a function that:
|
||||||
|
/// 1. Is marked as `async` and must be awaited
|
||||||
|
/// 2. Returns a `Result<T, Error>` with the response type
|
||||||
|
/// 3. Fails with an internal error if the client is not available
|
||||||
|
///
|
||||||
|
/// The semi-colon (`;`) separates the parameters from the return type.
|
||||||
|
///
|
||||||
|
/// This...
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// request!(show_document, params: ShowDocumentParams ; bool);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ...expands to:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// pub async fn show_document(params: ShowDocumentParams) -> Result<bool, Error> {
|
||||||
|
/// if let Some(client) = get_client() {
|
||||||
|
/// client.show_document(params).await
|
||||||
|
/// } else {
|
||||||
|
/// Err(Error::internal_error())
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
macro_rules! request {
|
||||||
|
($name:ident, $($param:ident: $type:ty),* ; $result:ty) => {
|
||||||
|
pub async fn $name($($param: $type),*) -> Result<$result, Error> {
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
client.$name($($param),*).await
|
||||||
|
} else {
|
||||||
|
Err(Error::internal_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod messages {
|
||||||
|
use tower_lsp_server::lsp_types::MessageActionItem;
|
||||||
|
use tower_lsp_server::lsp_types::MessageType;
|
||||||
|
use tower_lsp_server::lsp_types::ShowDocumentParams;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
use super::Display;
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
|
notify!(log_message, message_type: MessageType, message: impl Display + Send + 'static);
|
||||||
|
notify!(show_message, message_type: MessageType, message: impl Display + Send + 'static);
|
||||||
|
request!(show_message_request, message_type: MessageType, message: impl Display + Send + 'static, actions: Option<Vec<MessageActionItem>> ; Option<MessageActionItem>);
|
||||||
|
request!(show_document, params: ShowDocumentParams ; bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod diagnostics {
|
||||||
|
use tower_lsp_server::lsp_types::Diagnostic;
|
||||||
|
use tower_lsp_server::lsp_types::Uri;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
|
||||||
|
notify!(publish_diagnostics, uri: Uri, diagnostics: Vec<Diagnostic>, version: Option<i32>);
|
||||||
|
notify_discard!(workspace_diagnostic_refresh,);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod workspace {
|
||||||
|
use tower_lsp_server::lsp_types::ApplyWorkspaceEditResponse;
|
||||||
|
use tower_lsp_server::lsp_types::ConfigurationItem;
|
||||||
|
use tower_lsp_server::lsp_types::LSPAny;
|
||||||
|
use tower_lsp_server::lsp_types::WorkspaceEdit;
|
||||||
|
use tower_lsp_server::lsp_types::WorkspaceFolder;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
|
request!(apply_edit, edit: WorkspaceEdit ; ApplyWorkspaceEditResponse);
|
||||||
|
request!(configuration, items: Vec<ConfigurationItem> ; Vec<LSPAny>);
|
||||||
|
request!(workspace_folders, ; Option<Vec<WorkspaceFolder>>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod editor {
|
||||||
|
use super::get_client;
|
||||||
|
|
||||||
|
notify_discard!(code_lens_refresh,);
|
||||||
|
notify_discard!(semantic_tokens_refresh,);
|
||||||
|
notify_discard!(inline_value_refresh,);
|
||||||
|
notify_discard!(inlay_hint_refresh,);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod capabilities {
|
||||||
|
use tower_lsp_server::lsp_types::Registration;
|
||||||
|
use tower_lsp_server::lsp_types::Unregistration;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
|
||||||
|
notify_discard!(register_capability, registrations: Vec<Registration>);
|
||||||
|
notify_discard!(unregister_capability, unregisterations: Vec<Unregistration>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod monitoring {
|
||||||
|
use serde::Serialize;
|
||||||
|
use tower_lsp_server::lsp_types::ProgressToken;
|
||||||
|
use tower_lsp_server::Progress;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
|
||||||
|
pub fn telemetry_event<S: Serialize + Send + 'static>(data: S) {
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
client.telemetry_event(data).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn progress<T: Into<String> + Send>(token: ProgressToken, title: T) -> Option<Progress> {
|
||||||
|
get_client().map(|client| client.progress(token, title))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod protocol {
|
||||||
|
use tower_lsp_server::lsp_types::notification::Notification;
|
||||||
|
use tower_lsp_server::lsp_types::request::Request;
|
||||||
|
|
||||||
|
use super::get_client;
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
|
pub fn send_notification<N>(params: N::Params)
|
||||||
|
where
|
||||||
|
N: Notification,
|
||||||
|
N::Params: Send + 'static,
|
||||||
|
{
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
tokio::spawn(async move {
|
||||||
|
client.send_notification::<N>(params).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_request<R>(params: R::Params) -> Result<R::Result, Error>
|
||||||
|
where
|
||||||
|
R: Request,
|
||||||
|
R::Params: Send + 'static,
|
||||||
|
R::Result: Send + 'static,
|
||||||
|
{
|
||||||
|
if let Some(client) = get_client() {
|
||||||
|
client.send_request::<R>(params).await
|
||||||
|
} else {
|
||||||
|
Err(Error::internal_error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod client;
|
||||||
mod db;
|
mod db;
|
||||||
mod documents;
|
mod documents;
|
||||||
mod queue;
|
mod queue;
|
||||||
|
@ -20,7 +21,11 @@ pub fn run() -> Result<()> {
|
||||||
let stdin = tokio::io::stdin();
|
let stdin = tokio::io::stdin();
|
||||||
let stdout = tokio::io::stdout();
|
let stdout = tokio::io::stdout();
|
||||||
|
|
||||||
let (service, socket) = LspService::build(DjangoLanguageServer::new).finish();
|
let (service, socket) = LspService::build(|client| {
|
||||||
|
client::init_client(client);
|
||||||
|
DjangoLanguageServer::new()
|
||||||
|
})
|
||||||
|
.finish();
|
||||||
|
|
||||||
Server::new(stdin, stdout, socket).serve(service).await;
|
Server::new(stdin, stdout, socket).serve(service).await;
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ use tower_lsp_server::lsp_types::TextDocumentSyncKind;
|
||||||
use tower_lsp_server::lsp_types::TextDocumentSyncOptions;
|
use tower_lsp_server::lsp_types::TextDocumentSyncOptions;
|
||||||
use tower_lsp_server::lsp_types::WorkspaceFoldersServerCapabilities;
|
use tower_lsp_server::lsp_types::WorkspaceFoldersServerCapabilities;
|
||||||
use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
|
use tower_lsp_server::lsp_types::WorkspaceServerCapabilities;
|
||||||
use tower_lsp_server::Client;
|
|
||||||
use tower_lsp_server::LanguageServer;
|
use tower_lsp_server::LanguageServer;
|
||||||
|
|
||||||
|
use crate::client;
|
||||||
use crate::queue::Queue;
|
use crate::queue::Queue;
|
||||||
use crate::session::Session;
|
use crate::session::Session;
|
||||||
|
|
||||||
|
@ -32,16 +32,14 @@ const SERVER_NAME: &str = "Django Language Server";
|
||||||
const SERVER_VERSION: &str = "0.1.0";
|
const SERVER_VERSION: &str = "0.1.0";
|
||||||
|
|
||||||
pub struct DjangoLanguageServer {
|
pub struct DjangoLanguageServer {
|
||||||
client: Client,
|
|
||||||
session: Arc<RwLock<Session>>,
|
session: Arc<RwLock<Session>>,
|
||||||
queue: Queue,
|
queue: Queue,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DjangoLanguageServer {
|
impl DjangoLanguageServer {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(client: Client) -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
client,
|
|
||||||
session: Arc::new(RwLock::new(Session::default())),
|
session: Arc::new(RwLock::new(Session::default())),
|
||||||
queue: Queue::new(),
|
queue: Queue::new(),
|
||||||
}
|
}
|
||||||
|
@ -60,9 +58,7 @@ impl DjangoLanguageServer {
|
||||||
|
|
||||||
impl LanguageServer for DjangoLanguageServer {
|
impl LanguageServer for DjangoLanguageServer {
|
||||||
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
|
async fn initialize(&self, params: InitializeParams) -> LspResult<InitializeResult> {
|
||||||
self.client
|
client::log_message(MessageType::INFO, "Initializing server...");
|
||||||
.log_message(MessageType::INFO, "Initializing server...")
|
|
||||||
.await;
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
*session.client_capabilities_mut() = Some(params.capabilities);
|
*session.client_capabilities_mut() = Some(params.capabilities);
|
||||||
|
@ -108,12 +104,10 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
|
|
||||||
#[allow(clippy::too_many_lines)]
|
#[allow(clippy::too_many_lines)]
|
||||||
async fn initialized(&self, _params: InitializedParams) {
|
async fn initialized(&self, _params: InitializedParams) {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
"Server received initialized notification.",
|
"Server received initialized notification.",
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
let init_params = InitializeParams {
|
let init_params = InitializeParams {
|
||||||
// Using the current directory by default right now, but we should switch to
|
// Using the current directory by default right now, but we should switch to
|
||||||
|
@ -138,23 +132,18 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_project {
|
if has_project {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
"Project discovered from current directory",
|
"Project discovered from current directory",
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
} else {
|
} else {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
"No project discovered; running without project context",
|
"No project discovered; running without project context",
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let session_arc = Arc::clone(&self.session);
|
let session_arc = Arc::clone(&self.session);
|
||||||
let client = self.client.clone();
|
|
||||||
|
|
||||||
if let Err(e) = self
|
if let Err(e) = self
|
||||||
.queue
|
.queue
|
||||||
|
@ -170,22 +159,18 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((path_display, venv_path)) = project_path_and_venv {
|
if let Some((path_display, venv_path)) = project_path_and_venv {
|
||||||
client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!(
|
format!(
|
||||||
"Task: Starting initialization for project at: {path_display}"
|
"Task: Starting initialization for project at: {path_display}"
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
if let Some(ref path) = venv_path {
|
if let Some(ref path) = venv_path {
|
||||||
client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!("Using virtual environment from config: {path}"),
|
format!("Using virtual environment from config: {path}"),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let init_result = {
|
let init_result = {
|
||||||
|
@ -200,24 +185,20 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
|
|
||||||
match init_result {
|
match init_result {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!(
|
format!(
|
||||||
"Task: Successfully initialized project: {path_display}"
|
"Task: Successfully initialized project: {path_display}"
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::ERROR,
|
MessageType::ERROR,
|
||||||
&format!(
|
format!(
|
||||||
"Task: Failed to initialize Django project at {path_display}: {e}"
|
"Task: Failed to initialize Django project at {path_display}: {e}"
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
// Clear project on error
|
// Clear project on error
|
||||||
let mut session = session_arc.write().await;
|
let mut session = session_arc.write().await;
|
||||||
|
@ -225,27 +206,21 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
"Task: No project instance found to initialize.",
|
"Task: No project instance found to initialize.",
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::ERROR,
|
MessageType::ERROR,
|
||||||
&format!("Failed to submit project initialization task: {e}"),
|
format!("Failed to submit project initialization task: {e}"),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
} else {
|
} else {
|
||||||
self.client
|
client::log_message(MessageType::INFO, "Scheduled project initialization task.");
|
||||||
.log_message(MessageType::INFO, "Scheduled project initialization task.")
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,12 +229,10 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_open(&self, params: DidOpenTextDocumentParams) {
|
async fn did_open(&self, params: DidOpenTextDocumentParams) {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!("Opened document: {:?}", params.text_document.uri),
|
format!("Opened document: {:?}", params.text_document.uri),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
let db = session.db();
|
let db = session.db();
|
||||||
|
@ -269,12 +242,10 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
async fn did_change(&self, params: DidChangeTextDocumentParams) {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!("Changed document: {:?}", params.text_document.uri),
|
format!("Changed document: {:?}", params.text_document.uri),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
let db = session.db();
|
let db = session.db();
|
||||||
|
@ -284,12 +255,10 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_close(&self, params: DidCloseTextDocumentParams) {
|
async fn did_close(&self, params: DidCloseTextDocumentParams) {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
&format!("Closed document: {:?}", params.text_document.uri),
|
format!("Closed document: {:?}", params.text_document.uri),
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
self.with_session_mut(|session| {
|
self.with_session_mut(|session| {
|
||||||
session.documents_mut().handle_did_close(¶ms);
|
session.documents_mut().handle_did_close(¶ms);
|
||||||
|
@ -317,12 +286,10 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
|
async fn did_change_configuration(&self, _params: DidChangeConfigurationParams) {
|
||||||
self.client
|
client::log_message(
|
||||||
.log_message(
|
|
||||||
MessageType::INFO,
|
MessageType::INFO,
|
||||||
"Configuration change detected. Reloading settings...",
|
"Configuration change detected. Reloading settings...",
|
||||||
)
|
);
|
||||||
.await;
|
|
||||||
|
|
||||||
let project_path = self
|
let project_path = self
|
||||||
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
|
.with_session(|session| session.project().map(|p| p.path().to_path_buf()))
|
||||||
|
@ -334,7 +301,7 @@ impl LanguageServer for DjangoLanguageServer {
|
||||||
*session.settings_mut() = new_settings;
|
*session.settings_mut() = new_settings;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error loading settings: {e}");
|
client::log_message(MessageType::ERROR, format!("Error loading settings: {e}"));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue