Remove server_args from LspAdapter

Prepare to remove concept of a runtime from greater server startup code,
which is important for future language server extensibility

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
This commit is contained in:
Julia 2023-03-24 10:40:50 -04:00
parent ed442cfc8c
commit 1a2e509e35
14 changed files with 204 additions and 146 deletions

View file

@ -83,12 +83,17 @@ pub enum ServerExecutionKind {
Node,
}
#[derive(Debug, Clone, Deserialize)]
pub struct LanguageServerBinary {
pub path: PathBuf,
pub arguments: Vec<String>,
}
/// Represents a Language Server, with certain cached sync properties.
/// Uses [`LspAdapter`] under the hood, but calls all 'static' methods
/// once at startup, and caches the results.
pub struct CachedLspAdapter {
pub name: LanguageServerName,
pub server_args: Vec<String>,
pub initialization_options: Option<Value>,
pub disk_based_diagnostic_sources: Vec<String>,
pub disk_based_diagnostics_progress_token: Option<String>,
@ -99,7 +104,6 @@ pub struct CachedLspAdapter {
impl CachedLspAdapter {
pub async fn new(adapter: Arc<dyn LspAdapter>) -> Arc<Self> {
let name = adapter.name().await;
let server_args = adapter.server_args().await;
let initialization_options = adapter.initialization_options().await;
let disk_based_diagnostic_sources = adapter.disk_based_diagnostic_sources().await;
let disk_based_diagnostics_progress_token =
@ -108,7 +112,6 @@ impl CachedLspAdapter {
Arc::new(CachedLspAdapter {
name,
server_args,
initialization_options,
disk_based_diagnostic_sources,
disk_based_diagnostics_progress_token,
@ -129,13 +132,16 @@ impl CachedLspAdapter {
version: Box<dyn 'static + Send + Any>,
http: Arc<dyn HttpClient>,
container_dir: PathBuf,
) -> Result<PathBuf> {
) -> Result<LanguageServerBinary> {
self.adapter
.fetch_server_binary(version, http, container_dir)
.await
}
pub async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf> {
pub async fn cached_server_binary(
&self,
container_dir: PathBuf,
) -> Option<LanguageServerBinary> {
self.adapter.cached_server_binary(container_dir).await
}
@ -190,9 +196,9 @@ pub trait LspAdapter: 'static + Send + Sync {
version: Box<dyn 'static + Send + Any>,
http: Arc<dyn HttpClient>,
container_dir: PathBuf,
) -> Result<PathBuf>;
) -> Result<LanguageServerBinary>;
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<PathBuf>;
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary>;
async fn process_diagnostics(&self, _: &mut lsp::PublishDiagnosticsParams) {}
@ -215,10 +221,6 @@ pub trait LspAdapter: 'static + Send + Sync {
None
}
async fn server_args(&self) -> Vec<String> {
Vec::new()
}
async fn initialization_options(&self) -> Option<Value> {
None
}
@ -497,7 +499,7 @@ pub struct LanguageRegistry {
lsp_binary_paths: Mutex<
HashMap<
LanguageServerName,
Shared<BoxFuture<'static, Result<PathBuf, Arc<anyhow::Error>>>>,
Shared<BoxFuture<'static, Result<LanguageServerBinary, Arc<anyhow::Error>>>>,
>,
>,
executor: Option<Arc<Background>>,
@ -810,12 +812,12 @@ impl LanguageRegistry {
login_shell_env_loaded.await;
let node_path = node_path.await;
let server_binary_path = this
let server_binary = this
.lsp_binary_paths
.lock()
.entry(adapter.name.clone())
.or_insert_with(|| {
get_server_binary_path(
get_server_binary(
adapter.clone(),
language.clone(),
http_client,
@ -829,8 +831,9 @@ impl LanguageRegistry {
.clone()
.map_err(|e| anyhow!(e));
let server_binary_path = server_binary_path.await?;
let server_name = server_binary_path
let server_binary = server_binary.await?;
let server_name = server_binary
.path
.file_name()
.map(|name| name.to_string_lossy().to_string());
@ -839,16 +842,15 @@ impl LanguageRegistry {
let node_path = node_path
.ok_or(anyhow!("Missing Node path for Node based language server"))?;
let node_binary = node_path.join("bin/node");
dbg!(&node_binary);
let mut command = smol::process::Command::new(node_binary);
command.arg(dbg!(server_binary_path));
command.arg(dbg!(server_binary.path));
command
}
ServerExecutionKind::Launch => smol::process::Command::new(server_binary_path),
ServerExecutionKind::Launch => smol::process::Command::new(server_binary.path),
};
command.args(&adapter.server_args);
command.args(dbg!(&server_binary.arguments));
let server = lsp::LanguageServer::new(server_id, server_name, command, &root_path, cx)?;
Ok(server)
@ -880,13 +882,13 @@ impl Default for LanguageRegistry {
}
}
async fn get_server_binary_path(
async fn get_server_binary(
adapter: Arc<CachedLspAdapter>,
language: Arc<Language>,
http_client: Arc<dyn HttpClient>,
download_dir: Arc<Path>,
statuses: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
) -> Result<PathBuf> {
) -> Result<LanguageServerBinary> {
let container_dir = download_dir.join(adapter.name.0.as_ref());
if !container_dir.exists() {
smol::fs::create_dir_all(&container_dir)
@ -894,7 +896,7 @@ async fn get_server_binary_path(
.context("failed to create container directory")?;
}
let path = fetch_latest_server_binary_path(
let binary = fetch_latest_server_binary(
adapter.clone(),
language.clone(),
http_client,
@ -902,12 +904,12 @@ async fn get_server_binary_path(
statuses.clone(),
)
.await;
if let Err(error) = path.as_ref() {
if let Some(cached_path) = adapter.cached_server_binary(container_dir).await {
if let Err(error) = binary.as_ref() {
if let Some(cached) = adapter.cached_server_binary(container_dir).await {
statuses
.broadcast((language.clone(), LanguageServerBinaryStatus::Cached))
.await?;
return Ok(cached_path);
return Ok(cached);
} else {
statuses
.broadcast((
@ -919,16 +921,16 @@ async fn get_server_binary_path(
.await?;
}
}
path
binary
}
async fn fetch_latest_server_binary_path(
async fn fetch_latest_server_binary(
adapter: Arc<CachedLspAdapter>,
language: Arc<Language>,
http_client: Arc<dyn HttpClient>,
container_dir: &Path,
lsp_binary_statuses_tx: async_broadcast::Sender<(Arc<Language>, LanguageServerBinaryStatus)>,
) -> Result<PathBuf> {
) -> Result<LanguageServerBinary> {
let container_dir: Arc<Path> = container_dir.into();
lsp_binary_statuses_tx
.broadcast((
@ -942,13 +944,13 @@ async fn fetch_latest_server_binary_path(
lsp_binary_statuses_tx
.broadcast((language.clone(), LanguageServerBinaryStatus::Downloading))
.await?;
let path = adapter
let binary = adapter
.fetch_server_binary(version_info, http_client, container_dir.to_path_buf())
.await?;
lsp_binary_statuses_tx
.broadcast((language.clone(), LanguageServerBinaryStatus::Downloaded))
.await?;
Ok(path)
Ok(binary)
}
impl Language {
@ -1485,11 +1487,11 @@ impl LspAdapter for Arc<FakeLspAdapter> {
_: Box<dyn 'static + Send + Any>,
_: Arc<dyn HttpClient>,
_: PathBuf,
) -> Result<PathBuf> {
) -> Result<LanguageServerBinary> {
unreachable!();
}
async fn cached_server_binary(&self, _: PathBuf) -> Option<PathBuf> {
async fn cached_server_binary(&self, _: PathBuf) -> Option<LanguageServerBinary> {
unreachable!();
}