aboutsummaryrefslogtreecommitdiff
path: root/helix-lsp
diff options
context:
space:
mode:
Diffstat (limited to 'helix-lsp')
-rw-r--r--helix-lsp/Cargo.toml2
-rw-r--r--helix-lsp/src/client.rs6
-rw-r--r--helix-lsp/src/lib.rs35
3 files changed, 37 insertions, 6 deletions
diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml
index 536a6ba6..ad432d96 100644
--- a/helix-lsp/Cargo.toml
+++ b/helix-lsp/Cargo.toml
@@ -23,5 +23,5 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0"
tokio = { version = "1.21", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
-tokio-stream = "0.1.10"
+tokio-stream = "0.1.11"
which = "4.2"
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 497ce80c..0b443ccf 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -49,6 +49,7 @@ impl Client {
root_markers: &[String],
id: usize,
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))?;
@@ -72,7 +73,10 @@ impl Client {
let (server_rx, server_tx, initialize_notify) =
Transport::start(reader, writer, stderr, id);
- let root_path = find_root(None, root_markers);
+ let root_path = find_root(
+ doc_path.and_then(|x| x.parent().and_then(|x| x.to_str())),
+ root_markers,
+ );
let root_uri = lsp::Url::from_file_path(root_path.clone()).ok();
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index cb234357..feeedc96 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -204,6 +204,20 @@ pub mod util {
// in reverse order.
edits.sort_unstable_by_key(|edit| edit.range.start);
+ // Generate a diff if the edit is a full document replacement.
+ #[allow(clippy::collapsible_if)]
+ if edits.len() == 1 {
+ let is_document_replacement = edits.first().and_then(|edit| {
+ let start = lsp_pos_to_pos(doc, edit.range.start, offset_encoding)?;
+ let end = lsp_pos_to_pos(doc, edit.range.end, offset_encoding)?;
+ Some(start..end)
+ }) == Some(0..doc.len_chars());
+ if is_document_replacement {
+ let new_text = Rope::from(edits.pop().unwrap().new_text);
+ return helix_core::diff::compare_ropes(doc, &new_text);
+ }
+ }
+
Transaction::change(
doc,
edits.into_iter().map(|edit| {
@@ -339,6 +353,7 @@ impl Registry {
pub fn restart(
&mut self,
language_config: &LanguageConfiguration,
+ doc_path: Option<&std::path::PathBuf>,
) -> Result<Option<Arc<Client>>> {
let config = match &language_config.language_server {
Some(config) => config,
@@ -353,17 +368,26 @@ impl Registry {
// initialize a new client
let id = self.counter.fetch_add(1, Ordering::Relaxed);
- let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
+ let NewClientResult(client, incoming) =
+ start_client(id, language_config, config, doc_path)?;
self.incoming.push(UnboundedReceiverStream::new(incoming));
- entry.insert((id, client.clone()));
+ let (_, old_client) = entry.insert((id, client.clone()));
+
+ tokio::spawn(async move {
+ let _ = old_client.force_shutdown().await;
+ });
Ok(Some(client))
}
}
}
- pub fn get(&mut self, language_config: &LanguageConfiguration) -> Result<Option<Arc<Client>>> {
+ pub fn get(
+ &mut self,
+ language_config: &LanguageConfiguration,
+ doc_path: Option<&std::path::PathBuf>,
+ ) -> Result<Option<Arc<Client>>> {
let config = match &language_config.language_server {
Some(config) => config,
None => return Ok(None),
@@ -375,7 +399,8 @@ impl Registry {
// initialize a new client
let id = self.counter.fetch_add(1, Ordering::Relaxed);
- let NewClientResult(client, incoming) = start_client(id, language_config, config)?;
+ let NewClientResult(client, incoming) =
+ start_client(id, language_config, config, doc_path)?;
self.incoming.push(UnboundedReceiverStream::new(incoming));
entry.insert((id, client.clone()));
@@ -475,6 +500,7 @@ fn start_client(
id: usize,
config: &LanguageConfiguration,
ls_config: &LanguageServerConfiguration,
+ doc_path: Option<&std::path::PathBuf>,
) -> Result<NewClientResult> {
let (client, incoming, initialize_notify) = Client::start(
&ls_config.command,
@@ -483,6 +509,7 @@ fn start_client(
&config.roots,
id,
ls_config.timeout,
+ doc_path,
)?;
let client = Arc::new(client);