Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 53 additions & 3 deletions crates/language_extension/src/extension_lsp_adapter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::ops::Range;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::sync::Arc;

use anyhow::{Context as _, Result};
Expand Down Expand Up @@ -174,7 +174,32 @@ impl DynLspInstaller for ExtensionLspAdapter {
)
.await?;

let path = self.extension.path_from_extension(command.command.as_ref());
// on windows, extensions might produce weird paths
// that start with a leading slash due to WASI
// requiring that for PWD and friends so account for
// that here and try to transform those paths back
// to windows paths
//
// if we don't do this, std will interpret the path as relative,
// which changes join behavior
let command_path: &Path = if cfg!(windows)
&& let Some(command) = command.command.to_str()
{
let mut chars = command.chars();
if chars.next().is_some_and(|c| c == '/')
&& chars.next().is_some_and(|c| c.is_ascii_alphabetic())
&& chars.next().is_some_and(|c| c == ':')
&& chars.next().is_some_and(|c| c == '\\' || c == '/')
{
// looks like a windows path with a leading slash, so strip it
command.strip_prefix('/').unwrap().as_ref()
} else {
command.as_ref()
}
} else {
command.command.as_ref()
};
let path = self.extension.path_from_extension(command_path);

// TODO: This should now be done via the `zed::make_file_executable` function in
// Zed extension API, but we're leaving these existing usages in place temporarily
Expand All @@ -193,7 +218,32 @@ impl DynLspInstaller for ExtensionLspAdapter {

Ok(LanguageServerBinary {
path,
arguments: command.args.into_iter().map(|arg| arg.into()).collect(),
arguments: command
.args
.into_iter()
.map(|arg| {
// on windows, extensions might produce weird paths
// that start with a leading slash due to WASI
// requiring that for PWD and friends so account for
// that here and try to transform those paths back
// to windows paths
if cfg!(windows) {
let mut chars = arg.chars();
if chars.next().is_some_and(|c| c == '/')
&& chars.next().is_some_and(|c| c.is_ascii_alphabetic())
&& chars.next().is_some_and(|c| c == ':')
&& chars.next().is_some_and(|c| c == '\\' || c == '/')
{
// looks like a windows path with a leading slash, so strip it
arg.strip_prefix('/').unwrap().into()
} else {
arg.into()
}
} else {
arg.into()
}
})
.collect(),
env: Some(command.env.into_iter().collect()),
})
})
Expand Down