mirror of
https://github.com/denoland/deno.git
synced 2025-09-26 12:19:12 +00:00
fix(lsp): close server on exit notification (#28232)
This commit is contained in:
parent
a9f404e479
commit
876bac445a
7 changed files with 19 additions and 35 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -1570,9 +1570,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno-tower-lsp-macros"
|
name = "deno-tower-lsp-macros"
|
||||||
version = "0.10.0"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e017686632f7908cde3e02cd1598e25488f57448600a09211834cfd547b9ec39"
|
checksum = "61083feefc9c29a3f45670be6b60001ec209286c861b6830cd30ba4af9a6e9d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2691,9 +2691,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_tower_lsp"
|
name = "deno_tower_lsp"
|
||||||
version = "0.3.0"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c58d75640e2edffc77929064f2f13c308e549b4b5c42ea6159b0607add856675"
|
checksum = "c29dce82d67177bbc36468f64cddd8c25242fc31b99369ef0126fa7fad64c5ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"auto_impl",
|
"auto_impl",
|
||||||
|
|
|
@ -218,7 +218,7 @@ tokio-socks = "0.5.1"
|
||||||
tokio-util = "0.7.4"
|
tokio-util = "0.7.4"
|
||||||
tower = { version = "0.5.2", default-features = false, features = ["retry", "util"] }
|
tower = { version = "0.5.2", default-features = false, features = ["retry", "util"] }
|
||||||
tower-http = { version = "0.6.1", features = ["decompression-br", "decompression-gzip"] }
|
tower-http = { version = "0.6.1", features = ["decompression-br", "decompression-gzip"] }
|
||||||
tower-lsp = { package = "deno_tower_lsp", version = "=0.3.0", features = ["proposed"] }
|
tower-lsp = { package = "deno_tower_lsp", version = "=0.4.2", features = ["proposed"] }
|
||||||
tower-service = "0.3.2"
|
tower-service = "0.3.2"
|
||||||
twox-hash = "=1.6.3"
|
twox-hash = "=1.6.3"
|
||||||
url = { version = "2.5", features = ["serde", "expose_internals"] }
|
url = { version = "2.5", features = ["serde", "expose_internals"] }
|
||||||
|
|
|
@ -137,7 +137,6 @@ pub struct LanguageServer {
|
||||||
/// https://github.com/Microsoft/language-server-protocol/issues/567#issuecomment-2085131917
|
/// https://github.com/Microsoft/language-server-protocol/issues/567#issuecomment-2085131917
|
||||||
init_flag: AsyncFlag,
|
init_flag: AsyncFlag,
|
||||||
performance: Arc<Performance>,
|
performance: Arc<Performance>,
|
||||||
shutdown_flag: AsyncFlag,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Snapshot of the state used by TSC.
|
/// Snapshot of the state used by TSC.
|
||||||
|
@ -227,7 +226,7 @@ pub struct Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LanguageServer {
|
impl LanguageServer {
|
||||||
pub fn new(client: Client, shutdown_flag: AsyncFlag) -> Self {
|
pub fn new(client: Client) -> Self {
|
||||||
let performance = Arc::new(Performance::default());
|
let performance = Arc::new(Performance::default());
|
||||||
Self {
|
Self {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
|
@ -237,7 +236,6 @@ impl LanguageServer {
|
||||||
))),
|
))),
|
||||||
init_flag: Default::default(),
|
init_flag: Default::default(),
|
||||||
performance,
|
performance,
|
||||||
shutdown_flag,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3566,7 +3564,6 @@ impl tower_lsp::LanguageServer for LanguageServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown(&self) -> LspResult<()> {
|
async fn shutdown(&self) -> LspResult<()> {
|
||||||
self.shutdown_flag.raise();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::unsync::spawn;
|
|
||||||
pub use repl::ReplCompletionItem;
|
pub use repl::ReplCompletionItem;
|
||||||
pub use repl::ReplLanguageServer;
|
pub use repl::ReplLanguageServer;
|
||||||
use tower_lsp::LspService;
|
use tower_lsp::LspService;
|
||||||
|
@ -9,7 +8,6 @@ use tower_lsp::Server;
|
||||||
|
|
||||||
use self::diagnostics::should_send_diagnostic_batch_index_notifications;
|
use self::diagnostics::should_send_diagnostic_batch_index_notifications;
|
||||||
use crate::lsp::language_server::LanguageServer;
|
use crate::lsp::language_server::LanguageServer;
|
||||||
use crate::util::sync::AsyncFlag;
|
|
||||||
|
|
||||||
mod analysis;
|
mod analysis;
|
||||||
mod cache;
|
mod cache;
|
||||||
|
@ -44,12 +42,8 @@ pub async fn start() -> Result<(), AnyError> {
|
||||||
let stdin = tokio::io::stdin();
|
let stdin = tokio::io::stdin();
|
||||||
let stdout = tokio::io::stdout();
|
let stdout = tokio::io::stdout();
|
||||||
|
|
||||||
let shutdown_flag = AsyncFlag::default();
|
|
||||||
let builder = LspService::build(|client| {
|
let builder = LspService::build(|client| {
|
||||||
language_server::LanguageServer::new(
|
language_server::LanguageServer::new(client::Client::from_tower(client))
|
||||||
client::Client::from_tower(client),
|
|
||||||
shutdown_flag.clone(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.custom_method(
|
.custom_method(
|
||||||
lsp_custom::PERFORMANCE_REQUEST,
|
lsp_custom::PERFORMANCE_REQUEST,
|
||||||
|
@ -76,19 +70,9 @@ pub async fn start() -> Result<(), AnyError> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (service, socket, pending) = builder.finish();
|
let (service, socket, pending) = builder.finish();
|
||||||
|
Server::new(stdin, stdout, socket, pending)
|
||||||
// TODO(nayeemrmn): This shutdown flag is a workaround for
|
.concurrency_level(32)
|
||||||
// https://github.com/denoland/deno/issues/20700. Remove when
|
.serve(service)
|
||||||
// https://github.com/ebkalderon/tower-lsp/issues/399 is fixed.
|
.await;
|
||||||
// Force end the server 8 seconds after receiving a shutdown request.
|
|
||||||
tokio::select! {
|
|
||||||
biased;
|
|
||||||
_ = Server::new(stdin, stdout, socket, pending).concurrency_level(32).serve(service) => {}
|
|
||||||
_ = spawn(async move {
|
|
||||||
shutdown_flag.wait_raised().await;
|
|
||||||
tokio::time::sleep(std::time::Duration::from_secs(8)).await;
|
|
||||||
}) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,8 @@ impl ReplLanguageServer {
|
||||||
super::logging::set_lsp_log_level(log::Level::Debug);
|
super::logging::set_lsp_log_level(log::Level::Debug);
|
||||||
super::logging::set_lsp_warn_level(log::Level::Debug);
|
super::logging::set_lsp_warn_level(log::Level::Debug);
|
||||||
|
|
||||||
let language_server = super::language_server::LanguageServer::new(
|
let language_server =
|
||||||
Client::new_for_repl(),
|
super::language_server::LanguageServer::new(Client::new_for_repl());
|
||||||
Default::default(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let cwd_uri = get_cwd_uri()?;
|
let cwd_uri = get_cwd_uri()?;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ fn lsp_startup_shutdown() {
|
||||||
let mut client = context.new_lsp_command().build();
|
let mut client = context.new_lsp_command().build();
|
||||||
client.initialize_default();
|
client.initialize_default();
|
||||||
client.shutdown();
|
client.shutdown();
|
||||||
|
assert!(client.wait_exit().unwrap().success());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -731,7 +731,7 @@ impl Drop for LspClient {
|
||||||
self.child.kill().unwrap();
|
self.child.kill().unwrap();
|
||||||
let _ = self.child.wait();
|
let _ = self.child.wait();
|
||||||
}
|
}
|
||||||
Ok(Some(status)) => panic!("deno lsp exited unexpectedly {status}"),
|
Ok(Some(_)) => {}
|
||||||
Err(e) => panic!("pebble error: {e}"),
|
Err(e) => panic!("pebble error: {e}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1002,6 +1002,10 @@ impl LspClient {
|
||||||
self.write_notification("exit", json!(null));
|
self.write_notification("exit", json!(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wait_exit(&mut self) -> std::io::Result<std::process::ExitStatus> {
|
||||||
|
self.child.wait()
|
||||||
|
}
|
||||||
|
|
||||||
// it's flaky to assert for a notification because a notification
|
// it's flaky to assert for a notification because a notification
|
||||||
// might arrive a little later, so only provide a method for asserting
|
// might arrive a little later, so only provide a method for asserting
|
||||||
// that there is no notification
|
// that there is no notification
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue