From 82a27eefa70deb35e3204e8b67e6dc055914bc4e Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Thu, 2 Nov 2023 09:40:35 +0100 Subject: [PATCH] Refactor lsp server into cli subcommand --- editors/vscode/src/client.ts | 1 + src/cli/mod.rs | 68 +++++++++--------------------------- src/cli/serve.rs | 45 ++++++++++++++++++++++++ src/server/mod.rs | 7 ++-- src/server/transport.rs | 50 ++++++++++++++++++++++++++ src/util/mod.rs | 2 -- src/util/transport.rs | 48 ------------------------- 7 files changed, 116 insertions(+), 105 deletions(-) create mode 100644 src/cli/serve.rs create mode 100644 src/server/transport.rs delete mode 100644 src/util/transport.rs diff --git a/editors/vscode/src/client.ts b/editors/vscode/src/client.ts index 988f9c6..65ba5ea 100644 --- a/editors/vscode/src/client.ts +++ b/editors/vscode/src/client.ts @@ -87,6 +87,7 @@ export const startServer = async () => { const server: Executable = { command, options, + args: ["serve"], }; // Create language server & client config diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 4d46f81..dedb8dd 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,69 +1,33 @@ -use ::tracing::debug; -use clap::Parser; - -use crate::server::{Server, ServerArguments}; -use crate::util::Transport; +use clap::{Parser, Subcommand}; +mod serve; mod tracing; -#[derive(Parser)] -struct Inner { - #[arg(long, alias = "port")] - pub socket: Option, - #[arg(long)] - pub stdio: bool, - #[arg(long, env)] - pub github_token: Option, -} +use serve::*; +use tracing::*; -impl Inner { - pub fn transport(&self) -> Option { - if let Some(port) = self.socket { - Some(Transport::Socket(port)) - } else if self.stdio { - Some(Transport::Stdio) - } else { - None - } - } +#[derive(Debug, Clone, Subcommand)] +pub enum CliSubcommand { + Serve(ServeCommand), } +#[derive(Debug, Clone, Parser)] +#[command(author, version, about, long_about = None)] pub struct Cli { - pub transport: Transport, - pub github_token: Option, + #[clap(subcommand)] + subcommand: CliSubcommand, } impl Cli { pub fn new() -> Self { - let arguments = Inner::parse(); - - let this = Self { - transport: arguments.transport().unwrap_or_default(), - github_token: arguments.github_token, - }; - - debug!( - "Parsed arguments\n\ttransport: {}\n\tgithub_token: {}", - this.transport, - if this.github_token.is_some() { - "Some(_)" - } else { - "None" - }, - ); - - this + Self::parse() } pub async fn run(self) { - // Set up tracing - tracing::setup_tracing(); + setup_tracing(); - // Create and run our language server - Server::serve(&ServerArguments { - transport: self.transport, - github_token: self.github_token, - }) - .await; + match self.subcommand { + CliSubcommand::Serve(cmd) => cmd.run().await, + } } } diff --git a/src/cli/serve.rs b/src/cli/serve.rs new file mode 100644 index 0000000..2e3695a --- /dev/null +++ b/src/cli/serve.rs @@ -0,0 +1,45 @@ +use clap::Parser; +use tracing::debug; + +use crate::server::{Server, ServerArguments, Transport}; + +#[derive(Debug, Clone, Parser)] +pub struct ServeCommand { + #[arg(long, alias = "port")] + pub socket: Option, + #[arg(long)] + pub stdio: bool, + #[arg(long, env)] + pub github_token: Option, +} + +impl ServeCommand { + fn transport(&self) -> Option { + if let Some(port) = self.socket { + Some(Transport::Socket(port)) + } else if self.stdio { + Some(Transport::Stdio) + } else { + None + } + } + + pub async fn run(self) { + let args = ServerArguments { + transport: self.transport().unwrap_or_default(), + github_token: self.github_token, + }; + + debug!( + "Parsed arguments\n\ttransport: {}\n\tgithub_token: {}", + args.transport, + if args.github_token.is_some() { + "Some(_)" + } else { + "None" + }, + ); + + Server::serve(&args).await; + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index e97eb0f..e6207af 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -6,14 +6,15 @@ use tower_lsp::{Client, LspService, Server as LspServer}; use crate::clients::*; use crate::tools::*; -use crate::util::*; mod document; mod initialize; mod language_server; mod requests; +mod transport; pub use document::*; +pub use transport::*; pub struct ServerArguments { pub transport: Transport, @@ -54,11 +55,11 @@ impl Server { match args.transport { Transport::Socket(port) => { - let (read, write) = create_socket(port).await; + let (read, write) = Transport::create_socket(port).await; LspServer::new(read, write, socket).serve(service).await; } Transport::Stdio => { - let (stdin, stdout) = create_stdio(); + let (stdin, stdout) = Transport::create_stdio(); LspServer::new(stdin, stdout, socket).serve(service).await; } } diff --git a/src/server/transport.rs b/src/server/transport.rs new file mode 100644 index 0000000..fbbfad8 --- /dev/null +++ b/src/server/transport.rs @@ -0,0 +1,50 @@ +use std::{fmt, net::SocketAddr}; + +use tokio::{ + io::{AsyncRead, AsyncWrite}, + net::TcpStream, +}; + +/** + Transport implementation for sockets and stdio. +*/ +#[derive(Debug, Default, Clone, Copy)] +#[non_exhaustive] +pub enum Transport { + Socket(u16), + #[default] + Stdio, +} + +impl Transport { + /** + Creates a socket listener. + */ + pub async fn create_socket(port: u16) -> (impl AsyncRead, impl AsyncWrite) { + let addr = SocketAddr::try_from(([127, 0, 0, 1], port)).unwrap(); + + let stream = TcpStream::connect(addr) + .await + .expect("Failed to connect to socket"); + + stream.into_split() + } + + /** + Get handles to standard input and output streams. + */ + pub fn create_stdio() -> (impl AsyncRead, impl AsyncWrite) { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + (stdin, stdout) + } +} + +impl fmt::Display for Transport { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Stdio => write!(f, "Stdio"), + Self::Socket(p) => write!(f, "Socket({p})"), + } + } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 2957b43..a10bb05 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,7 +1,5 @@ mod requests; -mod transport; mod uri; pub use requests::*; -pub use transport::*; pub use uri::*; diff --git a/src/util/transport.rs b/src/util/transport.rs deleted file mode 100644 index 6a47e93..0000000 --- a/src/util/transport.rs +++ /dev/null @@ -1,48 +0,0 @@ -use std::{fmt, net::SocketAddr}; - -use tokio::{ - io::{AsyncRead, AsyncWrite}, - net::TcpStream, -}; - -/** - Creates a socket listener. -*/ -pub async fn create_socket(port: u16) -> (impl AsyncRead, impl AsyncWrite) { - let addr = SocketAddr::try_from(([127, 0, 0, 1], port)).unwrap(); - - let stream = TcpStream::connect(addr) - .await - .expect("Failed to connect to socket"); - - stream.into_split() -} - -/** - Get handles to standard input and output streams. -*/ -pub fn create_stdio() -> (impl AsyncRead, impl AsyncWrite) { - let stdin = tokio::io::stdin(); - let stdout = tokio::io::stdout(); - (stdin, stdout) -} - -/** - Transport implementation for sockets and stdio. -*/ -#[derive(Debug, Default, Clone, Copy)] -#[non_exhaustive] -pub enum Transport { - Socket(u16), - #[default] - Stdio, -} - -impl fmt::Display for Transport { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Stdio => write!(f, "Stdio"), - Self::Socket(p) => write!(f, "Socket({p})"), - } - } -}