feat(cli): add lsp_proxy command to support stdin/stdout
MODIFY
crates/rome_cli/Cargo.toml
crates/rome_cli/Cargo.toml
@@ -32,7 +32,7 @@ thiserror = "1.0.30"
rayon = "1.5.1"
serde = { version = "1.0.133", features = ["derive"] }
serde_json = { version = "1.0.74" }
-tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt", "rt-multi-thread", "macros"] }
+tokio = { workspace = true, features = ["io-std", "io-util", "net", "time", "rt","sync", "rt-multi-thread", "macros"] }
anyhow = "1.0.52"
dashmap = { workspace = true }

MODIFY
crates/rome_cli/src/commands/daemon.rs
crates/rome_cli/src/commands/daemon.rs
use rome_console::{markup, ConsoleExt};
use rome_lsp::ServerFactory;
use rome_service::{workspace::WorkspaceClient, RomeError, TransportError};
-use std::env;
-use std::path::PathBuf;
-use std::{fs, io};
+use std::{env, fs, path::PathBuf};
+use tokio::io;
use tokio::runtime::Runtime;
use tracing::subscriber::Interest;
use tracing::{debug_span, metadata::LevelFilter, Instrument, Metadata};
@@ -16,7 +15,7 @@ use tracing_tree::HierarchicalLayer;
use crate::{
open_transport,
- service::{self, ensure_daemon, run_daemon},
+ service::{self, ensure_daemon, open_socket, run_daemon},
CliSession, Termination,
};
@@ -91,6 +90,59 @@ pub(crate) fn print_socket() -> Result<(), Termination> {
Ok(())
}
+pub(crate) fn lsp_proxy() -> Result<(), Termination> {
+ let rt = Runtime::new()?;
+ rt.block_on(start_lsp_proxy(&rt))?;
+
+ Ok(())
+}
+
+/// Start a proxy process.
+/// Receives a process via `stdin` and then copy the content to the LSP socket.
+/// Copy to the process on `stdout` when the LSP responds to a message
+async fn start_lsp_proxy(rt: &Runtime) -> Result<(), Termination> {
+ ensure_daemon().await?;
+
+ match open_socket().await? {
+ Some((mut owned_read_half, mut owned_write_half)) => {
+ // forward stdin to socket
+ let mut stdin = io::stdin();
+ let input_handle = rt.spawn(async move {
+ loop {
+ match io::copy(&mut stdin, &mut owned_write_half).await {
+ Ok(b) => {
+ if b == 0 {
+ return Ok(());
+ }
+ }
+ Err(err) => return Err(err),
+ };
+ }
+ });
+
+ // receive socket response to stdout
+ let mut stdout = io::stdout();
+ let out_put_handle = rt.spawn(async move {
+ loop {
+ match io::copy(&mut owned_read_half, &mut stdout).await {
+ Ok(b) => {
+ if b == 0 {
+ return Ok(());
+ }
+ }
+ Err(err) => return Err(err),
+ };
+ }
+ });
+
+ let _ = input_handle.await;
+ let _ = out_put_handle.await;
+ Ok(())
+ }
+ None => Ok(()),
+ }
+}
+
const fn log_file_name_prefix() -> &'static str {
"server.log"
}

MODIFY
crates/rome_cli/src/commands/help.rs
crates/rome_cli/src/commands/help.rs
@@ -12,6 +12,7 @@ const MAIN: Markup = markup! {
- "<Emphasis>"init"</Emphasis>" Bootstraps a new rome project
- "<Emphasis>"start"</Emphasis>" Start the Rome daemon server process
- "<Emphasis>"stop"</Emphasis>" Stop the Rome daemon server process
+ - "<Emphasis>"lsp-proxy"</Emphasis>" Acts as a server for the Language Server Protocol over stdin/stdout
- "<Emphasis>"rage"</Emphasis>" Prints information for debugging
- "<Emphasis>"version"</Emphasis>" Shows the Rome version information and quit
- "<Emphasis>"help"</Emphasis>" Prints this help message
@@ -95,6 +96,13 @@ const STOP: Markup = markup! {
rome stop"
};
+const START_LSP_PROXY: Markup = markup! {
+"Rome lsp-proxy: Acts as a server for the Language Server Protocol over stdin/stdout
+
+ "<Emphasis>"USAGE:"</Emphasis>"
+ rome lsp-proxy"
+};
+
const RAGE: Markup = markup! {
"Rome rage: Prints information for debugging
@@ -118,6 +126,7 @@ pub(crate) fn help(mut session: CliSession, command: Option<&str>) -> Result<(),
Some("init") => INIT,
Some("start") => START,
Some("stop") => STOP,
+ Some("lsp-proxy") => START_LSP_PROXY,
Some("version") => VERSION_HELP_TEXT,
Some("rage") => RAGE,

MODIFY
crates/rome_cli/src/lib.rs
crates/rome_cli/src/lib.rs
@@ -89,6 +89,7 @@ impl<'app> CliSession<'app> {
Some("start") => commands::daemon::start(self),
Some("stop") => commands::daemon::stop(self),
+ Some("lsp-proxy") => commands::daemon::lsp_proxy(),
// Internal commands
Some("__run_server") => commands::daemon::run_server(),

MODIFY
crates/rome_cli/src/service/mod.rs
crates/rome_cli/src/service/mod.rs
@@ -50,7 +50,7 @@ pub(crate) use self::windows::{ensure_daemon, print_socket, run_daemon};
#[cfg(unix)]
mod unix;
#[cfg(unix)]
-use self::unix::open_socket;
+pub(crate) use self::unix::open_socket;
#[cfg(unix)]
pub(crate) use self::unix::{ensure_daemon, print_socket, run_daemon};

feat(cli): add lsp_proxy command to support stdin/stdout (#3442)