Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-lsp/src/client.rs')
-rw-r--r--helix-lsp/src/client.rs47
1 files changed, 19 insertions, 28 deletions
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 682d4db6..f3f7e279 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -1,9 +1,12 @@
use crate::{
+ config::LanguageServerConfig,
find_lsp_workspace, jsonrpc,
transport::{Payload, Transport},
Call, Error, OffsetEncoding, Result,
};
+use anyhow::Context;
+use helix_config::{self as config, OptionManager};
use helix_core::{find_workspace, path, syntax::LanguageServerFeature, ChangeSet, Rope};
use helix_loader::{self, VERSION_AND_GIT_HASH};
use lsp::{
@@ -13,15 +16,14 @@ use lsp::{
};
use lsp_types as lsp;
use parking_lot::Mutex;
-use serde::Deserialize;
use serde_json::Value;
use std::future::Future;
+use std::path::PathBuf;
use std::process::Stdio;
use std::sync::{
atomic::{AtomicU64, Ordering},
Arc,
};
-use std::{collections::HashMap, path::PathBuf};
use tokio::{
io::{BufReader, BufWriter},
process::{Child, Command},
@@ -50,13 +52,11 @@ pub struct Client {
server_tx: UnboundedSender<Payload>,
request_counter: AtomicU64,
pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
- config: Option<Value>,
root_path: std::path::PathBuf,
root_uri: Option<lsp::Url>,
workspace_folders: Mutex<Vec<lsp::WorkspaceFolder>>,
initialize_notify: Arc<Notify>,
- /// workspace folders added while the server is still initializing
- req_timeout: u64,
+ config: Arc<OptionManager>,
}
impl Client {
@@ -170,23 +170,20 @@ impl Client {
#[allow(clippy::type_complexity, clippy::too_many_arguments)]
pub fn start(
- cmd: &str,
- args: &[String],
- config: Option<Value>,
- server_environment: HashMap<String, String>,
+ config: Arc<OptionManager>,
root_markers: &[String],
manual_roots: &[PathBuf],
id: usize,
name: String,
- req_timeout: u64,
doc_path: Option<&std::path::PathBuf>,
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
// Resolve path to the binary
- let cmd = which::which(cmd).map_err(|err| anyhow::anyhow!(err))?;
+ let cmd = which::which(config.command().as_deref().context("no command defined")?)
+ .map_err(|err| anyhow::anyhow!(err))?;
let process = Command::new(cmd)
- .envs(server_environment)
- .args(args)
+ .envs(config.enviorment().iter().map(|(k, v)| (&**k, &**v)))
+ .args(config.args().iter().map(|v| &**v))
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
@@ -233,7 +230,6 @@ impl Client {
request_counter: AtomicU64::new(0),
capabilities: OnceCell::new(),
config,
- req_timeout,
root_path,
root_uri,
workspace_folders: Mutex::new(workspace_folders),
@@ -374,8 +370,8 @@ impl Client {
.unwrap_or_default()
}
- pub fn config(&self) -> Option<&Value> {
- self.config.as_ref()
+ pub fn config(&self) -> config::Guard<Option<Box<Value>>> {
+ self.config.server_config()
}
pub async fn workspace_folders(
@@ -404,7 +400,7 @@ impl Client {
where
R::Params: serde::Serialize,
{
- self.call_with_timeout::<R>(params, self.req_timeout)
+ self.call_with_timeout::<R>(params, self.config.timeout())
}
fn call_with_timeout<R: lsp::request::Request>(
@@ -512,7 +508,7 @@ impl Client {
// -------------------------------------------------------------------------------------------
pub(crate) async fn initialize(&self, enable_snippets: bool) -> Result<lsp::InitializeResult> {
- if let Some(config) = &self.config {
+ if let Some(config) = &*self.config() {
log::info!("Using custom LSP config: {}", config);
}
@@ -524,7 +520,7 @@ impl Client {
// clients will prefer _uri if possible
root_path: self.root_path.to_str().map(|path| path.to_owned()),
root_uri: self.root_uri.clone(),
- initialization_options: self.config.clone(),
+ initialization_options: self.config().as_deref().cloned(),
capabilities: lsp::ClientCapabilities {
workspace: Some(lsp::WorkspaceClientCapabilities {
configuration: Some(true),
@@ -1152,17 +1148,12 @@ impl Client {
};
// merge FormattingOptions with 'config.format'
- let config_format = self
- .config
- .as_ref()
- .and_then(|cfg| cfg.get("format"))
- .and_then(|fmt| HashMap::<String, lsp::FormattingProperty>::deserialize(fmt).ok());
-
- let options = if let Some(mut properties) = config_format {
+ let mut config_format = self.config.format();
+ let options = if !config_format.is_empty() {
// passed in options take precedence over 'config.format'
- properties.extend(options.properties);
+ config_format.extend(options.properties);
lsp::FormattingOptions {
- properties,
+ properties: config_format,
..options
}
} else {