Use anyhow more idiomatically (#31052)

https://github.com/zed-industries/zed/issues/30972 brought up another
case where our context is not enough to track the actual source of the
issue: we get a general top-level error without inner error.

The reason for this was `.ok_or_else(|| anyhow!("failed to read HEAD
SHA"))?; ` on the top level.

The PR finally reworks the way we use anyhow to reduce such issues (or
at least make it simpler to bubble them up later in a fix).
On top of that, uses a few more anyhow methods for better readability.

* `.ok_or_else(|| anyhow!("..."))`, `map_err` and other similar error
conversion/option reporting cases are replaced with `context` and
`with_context` calls
* in addition to that, various `anyhow!("failed to do ...")` are
stripped with `.context("Doing ...")` messages instead to remove the
parasitic `failed to` text
* `anyhow::ensure!` is used instead of `if ... { return Err(...); }`
calls
* `anyhow::bail!` is used instead of `return Err(anyhow!(...));`

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2025-05-21 02:06:07 +03:00 committed by GitHub
parent 1e51a7ac44
commit 16366cf9f2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
294 changed files with 2037 additions and 2610 deletions

View file

@ -717,7 +717,7 @@ impl ExtensionStore {
let mut response = http_client
.get(url.as_ref(), Default::default(), true)
.await
.map_err(|err| anyhow!("error downloading extension: {}", err))?;
.context("downloading extension")?;
fs.remove_dir(
&extension_dir,
@ -1415,7 +1415,7 @@ impl ExtensionStore {
let is_dev = fs
.metadata(&extension_dir)
.await?
.ok_or_else(|| anyhow!("directory does not exist"))?
.context("directory does not exist")?
.is_symlink;
if let Ok(mut language_paths) = fs.read_dir(&extension_dir.join("languages")).await {

View file

@ -1,6 +1,6 @@
use std::{path::PathBuf, sync::Arc};
use anyhow::{Context as _, Result, anyhow};
use anyhow::{Context as _, Result};
use client::{TypedEnvelope, proto};
use collections::{HashMap, HashSet};
use extension::{
@ -295,7 +295,7 @@ impl HeadlessExtensionStore {
let extension = envelope
.payload
.extension
.with_context(|| anyhow!("Invalid InstallExtension request"))?;
.context("Invalid InstallExtension request")?;
extensions
.update(&mut cx, |extensions, cx| {

View file

@ -533,11 +533,11 @@ impl WasmHost {
pub fn writeable_path_from_extension(&self, id: &Arc<str>, path: &Path) -> Result<PathBuf> {
let extension_work_dir = self.work_dir.join(id.as_ref());
let path = normalize_path(&extension_work_dir.join(path));
if path.starts_with(&extension_work_dir) {
Ok(path)
} else {
Err(anyhow!("cannot write to path {}", path.display()))
}
anyhow::ensure!(
path.starts_with(&extension_work_dir),
"cannot write to path {path:?}",
);
Ok(path)
}
}
@ -569,7 +569,7 @@ pub fn parse_wasm_extension_version(
//
// By parsing the entirety of the Wasm bytes before we return, we're able to detect this problem
// earlier as an `Err` rather than as a panic.
version.ok_or_else(|| anyhow!("extension {} has no zed:api-version section", extension_id))
version.with_context(|| format!("extension {extension_id} has no zed:api-version section"))
}
fn parse_wasm_extension_version_custom_section(data: &[u8]) -> Option<SemanticVersion> {

View file

@ -83,11 +83,10 @@ pub fn authorize_access_to_unreleased_wasm_api_version(
}
};
if !allow_unreleased_version {
Err(anyhow!(
"unreleased versions of the extension API can only be used on development builds of Zed"
))?;
}
anyhow::ensure!(
allow_unreleased_version,
"unreleased versions of the extension API can only be used on development builds of Zed"
);
Ok(())
}
@ -774,7 +773,7 @@ impl Extension {
.await
}
Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
Err(anyhow!("`run_slash_command` not available prior to v0.1.0"))
anyhow::bail!("`run_slash_command` not available prior to v0.1.0");
}
}
}
@ -809,9 +808,9 @@ impl Extension {
Extension::V0_0_1(_)
| Extension::V0_0_4(_)
| Extension::V0_0_6(_)
| Extension::V0_1_0(_) => Err(anyhow!(
"`context_server_command` not available prior to v0.2.0"
)),
| Extension::V0_1_0(_) => {
anyhow::bail!("`context_server_command` not available prior to v0.2.0");
}
}
}
@ -836,9 +835,9 @@ impl Extension {
| Extension::V0_1_0(_)
| Extension::V0_2_0(_)
| Extension::V0_3_0(_)
| Extension::V0_4_0(_) => Err(anyhow!(
"`context_server_configuration` not available prior to v0.5.0"
)),
| Extension::V0_4_0(_) => {
anyhow::bail!("`context_server_configuration` not available prior to v0.5.0");
}
}
}
@ -854,9 +853,9 @@ impl Extension {
Extension::V0_3_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
Extension::V0_2_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
Extension::V0_1_0(ext) => ext.call_suggest_docs_packages(store, provider).await,
Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => Err(anyhow!(
"`suggest_docs_packages` not available prior to v0.1.0"
)),
Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
anyhow::bail!("`suggest_docs_packages` not available prior to v0.1.0");
}
}
}
@ -893,7 +892,7 @@ impl Extension {
.await
}
Extension::V0_0_1(_) | Extension::V0_0_4(_) | Extension::V0_0_6(_) => {
Err(anyhow!("`index_docs` not available prior to v0.1.0"))
anyhow::bail!("`index_docs` not available prior to v0.1.0");
}
}
}
@ -920,7 +919,7 @@ impl Extension {
Ok(Ok(dap_binary))
}
_ => Err(anyhow!("`get_dap_binary` not available prior to v0.6.0")),
_ => anyhow::bail!("`get_dap_binary` not available prior to v0.6.0"),
}
}
}

View file

@ -1,7 +1,7 @@
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
use ::http_client::{AsyncBody, HttpRequestExt};
use ::settings::{Settings, WorktreeId};
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{Context as _, Result, bail};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use extension::{ExtensionLanguageServerProxy, KeyValueStoreDelegate, WorktreeDelegate};
@ -365,7 +365,7 @@ impl From<http_client::HttpMethod> for ::http_client::Method {
fn convert_request(
extension_request: &http_client::HttpRequest,
) -> Result<::http_client::Request<AsyncBody>, anyhow::Error> {
) -> anyhow::Result<::http_client::Request<AsyncBody>> {
let mut request = ::http_client::Request::builder()
.method(::http_client::Method::from(extension_request.method))
.uri(&extension_request.url)
@ -389,7 +389,7 @@ fn convert_request(
async fn convert_response(
response: &mut ::http_client::Response<AsyncBody>,
) -> Result<http_client::HttpResponse, anyhow::Error> {
) -> anyhow::Result<http_client::HttpResponse> {
let mut extension_response = http_client::HttpResponse {
body: Vec::new(),
headers: Vec::new(),
@ -508,14 +508,13 @@ impl ExtensionImports for WasmState {
.http_client
.get(&url, Default::default(), true)
.await
.map_err(|err| anyhow!("error downloading release: {}", err))?;
.context("downloading release")?;
if !response.status().is_success() {
Err(anyhow!(
"download failed with status {}",
response.status().to_string()
))?;
}
anyhow::ensure!(
response.status().is_success(),
"download failed with status {}",
response.status().to_string()
);
let body = BufReader::new(response.body_mut());
match file_type {
@ -568,7 +567,7 @@ impl ExtensionImports for WasmState {
use std::os::unix::fs::PermissionsExt;
return fs::set_permissions(&path, Permissions::from_mode(0o755))
.map_err(|error| anyhow!("failed to set permissions for path {path:?}: {error}"))
.with_context(|| format!("setting permissions for path {path:?}"))
.to_wasmtime_result();
}

View file

@ -9,7 +9,7 @@ use crate::wasm_host::wit::{CompletionKind, CompletionLabelDetails, InsertTextFo
use crate::wasm_host::{WasmState, wit::ToWasmtimeResult};
use ::http_client::{AsyncBody, HttpRequestExt};
use ::settings::{Settings, WorktreeId};
use anyhow::{Context, Result, anyhow, bail};
use anyhow::{Context as _, Result, bail};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use async_trait::async_trait;
@ -524,7 +524,7 @@ impl From<http_client::HttpMethod> for ::http_client::Method {
fn convert_request(
extension_request: &http_client::HttpRequest,
) -> Result<::http_client::Request<AsyncBody>, anyhow::Error> {
) -> anyhow::Result<::http_client::Request<AsyncBody>> {
let mut request = ::http_client::Request::builder()
.method(::http_client::Method::from(extension_request.method))
.uri(&extension_request.url)
@ -548,7 +548,7 @@ fn convert_request(
async fn convert_response(
response: &mut ::http_client::Response<AsyncBody>,
) -> Result<http_client::HttpResponse, anyhow::Error> {
) -> anyhow::Result<http_client::HttpResponse> {
let mut extension_response = http_client::HttpResponse {
body: Vec::new(),
headers: Vec::new(),
@ -871,14 +871,13 @@ impl ExtensionImports for WasmState {
.http_client
.get(&url, Default::default(), true)
.await
.map_err(|err| anyhow!("error downloading release: {}", err))?;
.context("downloading release")?;
if !response.status().is_success() {
Err(anyhow!(
"download failed with status {}",
response.status().to_string()
))?;
}
anyhow::ensure!(
response.status().is_success(),
"download failed with status {}",
response.status().to_string()
);
let body = BufReader::new(response.body_mut());
match file_type {
@ -931,7 +930,7 @@ impl ExtensionImports for WasmState {
use std::os::unix::fs::PermissionsExt;
return fs::set_permissions(&path, Permissions::from_mode(0o755))
.map_err(|error| anyhow!("failed to set permissions for path {path:?}: {error}"))
.with_context(|| format!("setting permissions for path {path:?}"))
.to_wasmtime_result();
}