Skip to content
Open
Show file tree
Hide file tree
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
27 changes: 16 additions & 11 deletions src/language_servers/csharp_ls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,25 @@ impl CsharpLs {
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);

let version = self.nuget.get_latest_version(PACKAGE_ID)?;
let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, version);
let version_dir = if let Ok(version) = self.nuget.get_latest_version(PACKAGE_ID) {
let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, version);

if Self::find_dll(&version_dir).is_err() {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);
if Self::find_dll(&version_dir).is_err() {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);

self.nuget
.download_and_extract(PACKAGE_ID, &version, &version_dir)?;
self.nuget
.download_and_extract(PACKAGE_ID, &version, &version_dir)?;

util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}
util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}

version_dir
} else {
util::find_offline_version(Self::LANGUAGE_SERVER_ID)?
};

let dll_path = Self::find_dll(&version_dir)?;
let command = Self::dotnet_exec(worktree, &dll_path, binary_args)?;
Expand Down
107 changes: 58 additions & 49 deletions src/language_servers/omnisharp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::fs;
use zed_extension_api::{self as zed, settings::LspSettings, LanguageServerId, Result};
use zed_extension_api::{self as zed, settings::LspSettings, LanguageServerId, Os, Result};

use crate::language_servers::util;

Expand Down Expand Up @@ -60,68 +60,77 @@ impl Omnisharp {
language_server_id,
&zed::LanguageServerInstallationStatus::CheckingForUpdate,
);
let release = zed::latest_github_release(
let (platform, arch) = zed::current_platform();
let binary_path = if let Ok(release) = zed::latest_github_release(
"OmniSharp/omnisharp-roslyn",
zed::GithubReleaseOptions {
require_assets: true,
pre_release: false,
},
)?;
) {
let asset_name = format!(
"omnisharp-{os}-{arch}-net6.0.{extension}",
os = match platform {
zed::Os::Mac => "osx",
zed::Os::Linux => "linux",
zed::Os::Windows => "win",
},
arch = match arch {
zed::Architecture::Aarch64 => "arm64",
zed::Architecture::X86 => "x86",
zed::Architecture::X8664 => "x64",
},
extension = match platform {
zed::Os::Mac | zed::Os::Linux => "tar.gz",
zed::Os::Windows => "zip",
}
);

let (platform, arch) = zed::current_platform();
let asset_name = format!(
"omnisharp-{os}-{arch}-net6.0.{extension}",
os = match platform {
zed::Os::Mac => "osx",
zed::Os::Linux => "linux",
zed::Os::Windows => "win",
},
arch = match arch {
zed::Architecture::Aarch64 => "arm64",
zed::Architecture::X86 => "x86",
zed::Architecture::X8664 => "x64",
},
extension = match platform {
zed::Os::Mac | zed::Os::Linux => "tar.gz",
zed::Os::Windows => "zip",
let asset = release
.assets
.iter()
.find(|asset| asset.name == asset_name)
.ok_or_else(|| format!("no asset found matching {:?}", asset_name))?;

let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, release.version);
let binary_path = Self::get_binary_path(&version_dir, platform);

if !fs::metadata(&binary_path).is_ok_and(|stat| stat.is_file()) {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);

zed::download_file(
&asset.download_url,
&version_dir,
match platform {
zed::Os::Mac | zed::Os::Linux => zed::DownloadedFileType::GzipTar,
zed::Os::Windows => zed::DownloadedFileType::Zip,
},
)
.map_err(|e| format!("failed to download file: {e}"))?;

util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}
);

let asset = release
.assets
.iter()
.find(|asset| asset.name == asset_name)
.ok_or_else(|| format!("no asset found matching {:?}", asset_name))?;

let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, release.version);
let binary_path = match platform {
zed::Os::Windows => format!("{version_dir}/OmniSharp.exe"),
_ => format!("{version_dir}/OmniSharp"),
binary_path
} else {
let version_dir = util::find_offline_version(Self::LANGUAGE_SERVER_ID)?;
Self::get_binary_path(&version_dir, platform)
};

if !fs::metadata(&binary_path).is_ok_and(|stat| stat.is_file()) {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);

zed::download_file(
&asset.download_url,
&version_dir,
match platform {
zed::Os::Mac | zed::Os::Linux => zed::DownloadedFileType::GzipTar,
zed::Os::Windows => zed::DownloadedFileType::Zip,
},
)
.map_err(|e| format!("failed to download file: {e}"))?;

util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}

self.cached_binary_path = Some(binary_path.clone());
Ok(OmnisharpBinary {
path: binary_path,
args: binary_args,
})
}

fn get_binary_path(version_dir: &str, platform: Os) -> String {
match platform {
zed::Os::Windows => format!("{version_dir}/OmniSharp.exe"),
_ => format!("{version_dir}/OmniSharp"),
}
}
}
31 changes: 18 additions & 13 deletions src/language_servers/roslyn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,28 @@ impl Roslyn {
};

let package_id = format!("{PACKAGE_PREFIX}.{rid}");
let version = self.nuget.get_latest_version(&package_id)?;
let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, version);
let version_dir = if let Ok(version) = self.nuget.get_latest_version(&package_id) {
let version_dir = format!("{}-{}", Self::LANGUAGE_SERVER_ID, version);

let already_installed = Self::find_server_path(rid, &version_dir)
.is_ok_and(|sp| fs::metadata(sp.as_str()).is_ok_and(|stat| stat.is_file()));
let already_installed = Self::find_server_path(rid, &version_dir)
.is_ok_and(|sp| fs::metadata(sp.as_str()).is_ok_and(|stat| stat.is_file()));

if !already_installed {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);
if !already_installed {
zed::set_language_server_installation_status(
language_server_id,
&zed::LanguageServerInstallationStatus::Downloading,
);

self.nuget
.download_and_extract(&package_id, &version, &version_dir)?;
self.nuget
.download_and_extract(&package_id, &version, &version_dir)?;

util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}
util::remove_outdated_versions(Self::LANGUAGE_SERVER_ID, &version_dir)?;
}

version_dir
} else {
util::find_offline_version(Self::LANGUAGE_SERVER_ID)?
};

let server_path = Self::find_server_path(rid, &version_dir)?;
if let ServerPath::Exe(ref path) = server_path {
Expand Down
13 changes: 13 additions & 0 deletions src/language_servers/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,16 @@ pub(super) fn remove_outdated_versions(
}
Ok(())
}

pub(super) fn find_offline_version(language_server_id: &'static str) -> Result<String> {
let entries = fs::read_dir(".").map_err(|e| format!("failed to list working directory {e}"))?;
for entry in entries {
let entry = entry.map_err(|e| format!("failed to load directory entry {e}"))?;
if let Ok(name) = entry.file_name().into_string() {
if name.starts_with(language_server_id) {
return Ok(name);
}
}
}
Err(format!("couldn't find installed language server version; try connecting to the internet"))
}