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

@ -17,7 +17,7 @@ use crate::{
task_context::RunnableRange,
text_diff::text_diff,
};
use anyhow::{Context as _, Result, anyhow};
use anyhow::{Context as _, Result};
use async_watch as watch;
pub use clock::ReplicaId;
use clock::{AGENT_REPLICA_ID, Lamport};
@ -816,13 +816,11 @@ impl Buffer {
message: proto::BufferState,
file: Option<Arc<dyn File>>,
) -> Result<Self> {
let buffer_id = BufferId::new(message.id)
.with_context(|| anyhow!("Could not deserialize buffer_id"))?;
let buffer_id = BufferId::new(message.id).context("Could not deserialize buffer_id")?;
let buffer = TextBuffer::new(replica_id, buffer_id, message.base_text);
let mut this = Self::build(buffer, file, capability);
this.text.set_line_ending(proto::deserialize_line_ending(
rpc::proto::LineEnding::from_i32(message.line_ending)
.ok_or_else(|| anyhow!("missing line_ending"))?,
rpc::proto::LineEnding::from_i32(message.line_ending).context("missing line_ending")?,
));
this.saved_version = proto::deserialize_version(&message.saved_version);
this.saved_mtime = message.saved_mtime.map(|time| time.into());

View file

@ -24,7 +24,7 @@ pub mod buffer_tests;
pub use crate::language_settings::EditPredictionsMode;
use crate::language_settings::SoftWrap;
use anyhow::{Context as _, Result, anyhow};
use anyhow::{Context as _, Result};
use async_trait::async_trait;
use collections::{HashMap, HashSet, IndexSet};
use fs::Fs;
@ -368,9 +368,7 @@ pub trait LspAdapter: 'static + Send + Sync {
}
}
if !binary_options.allow_binary_download {
return Err(anyhow!("downloading language servers disabled"));
}
anyhow::ensure!(binary_options.allow_binary_download, "downloading language servers disabled");
if let Some(cached_binary) = cached_binary.as_ref() {
return Ok(cached_binary.clone());
@ -1296,17 +1294,13 @@ impl Language {
}
pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
grammar.highlights_query = Some(Query::new(&grammar.ts_language, source)?);
Ok(self)
}
pub fn with_runnable_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut extra_captures = Vec::with_capacity(query.capture_names().len());
@ -1329,9 +1323,7 @@ impl Language {
}
pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut item_capture_ix = None;
let mut name_capture_ix = None;
@ -1368,9 +1360,7 @@ impl Language {
}
pub fn with_text_object_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut text_objects_by_capture_ix = Vec::new();
@ -1388,9 +1378,7 @@ impl Language {
}
pub fn with_embedding_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut item_capture_ix = None;
let mut name_capture_ix = None;
@ -1421,9 +1409,7 @@ impl Language {
}
pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut open_capture_ix = None;
let mut close_capture_ix = None;
@ -1458,9 +1444,7 @@ impl Language {
}
pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut indent_capture_ix = None;
let mut start_capture_ix = None;
@ -1488,9 +1472,7 @@ impl Language {
}
pub fn with_injection_query(mut self, source: &str) -> Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut language_capture_ix = None;
let mut injection_language_capture_ix = None;
@ -1508,18 +1490,14 @@ impl Language {
language_capture_ix = match (language_capture_ix, injection_language_capture_ix) {
(None, Some(ix)) => Some(ix),
(Some(_), Some(_)) => {
return Err(anyhow!(
"both language and injection.language captures are present"
));
anyhow::bail!("both language and injection.language captures are present");
}
_ => language_capture_ix,
};
content_capture_ix = match (content_capture_ix, injection_content_capture_ix) {
(None, Some(ix)) => Some(ix),
(Some(_), Some(_)) => {
return Err(anyhow!(
"both content and injection.content captures are present"
));
anyhow::bail!("both content and injection.content captures are present")
}
_ => content_capture_ix,
};
@ -1553,10 +1531,7 @@ impl Language {
pub fn with_override_query(mut self, source: &str) -> anyhow::Result<Self> {
let query = {
let grammar = self
.grammar
.as_ref()
.ok_or_else(|| anyhow!("no grammar for language"))?;
let grammar = self.grammar.as_ref().context("no grammar for language")?;
Query::new(&grammar.ts_language, source)?
};
@ -1607,10 +1582,10 @@ impl Language {
.values()
.any(|entry| entry.name == *referenced_name)
{
Err(anyhow!(
anyhow::bail!(
"language {:?} has overrides in config not in query: {referenced_name:?}",
self.config.name
))?;
);
}
}
@ -1633,9 +1608,7 @@ impl Language {
self.config.brackets.disabled_scopes_by_bracket_ix.clear();
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
grammar.override_config = Some(OverrideConfig {
query,
values: override_configs_by_id,
@ -1644,9 +1617,7 @@ impl Language {
}
pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
let grammar = self
.grammar_mut()
.ok_or_else(|| anyhow!("cannot mutate grammar"))?;
let grammar = self.grammar_mut().context("cannot mutate grammar")?;
let query = Query::new(&grammar.ts_language, source)?;
let mut redaction_capture_ix = None;
@ -2190,18 +2161,16 @@ pub fn point_from_lsp(point: lsp::Position) -> Unclipped<PointUtf16> {
}
pub fn range_to_lsp(range: Range<PointUtf16>) -> Result<lsp::Range> {
if range.start > range.end {
Err(anyhow!(
"Inverted range provided to an LSP request: {:?}-{:?}",
range.start,
range.end
))
} else {
Ok(lsp::Range {
start: point_to_lsp(range.start),
end: point_to_lsp(range.end),
})
}
anyhow::ensure!(
range.start <= range.end,
"Inverted range provided to an LSP request: {:?}-{:?}",
range.start,
range.end
);
Ok(lsp::Range {
start: point_to_lsp(range.start),
end: point_to_lsp(range.end),
})
}
pub fn range_from_lsp(range: lsp::Range) -> Range<Unclipped<PointUtf16>> {

View file

@ -873,15 +873,13 @@ impl LanguageRegistry {
}
}
Err(e) => {
log::error!("failed to load language {name}:\n{:?}", e);
log::error!("failed to load language {name}:\n{e:?}");
let mut state = this.state.write();
state.mark_language_loaded(id);
if let Some(mut txs) = state.loading_languages.remove(&id) {
for tx in txs.drain(..) {
let _ = tx.send(Err(anyhow!(
"failed to load language {}: {}",
name,
e
"failed to load language {name}: {e}",
)));
}
}
@ -944,7 +942,7 @@ impl LanguageRegistry {
let grammar_name = wasm_path
.file_stem()
.and_then(OsStr::to_str)
.ok_or_else(|| anyhow!("invalid grammar filename"))?;
.context("invalid grammar filename")?;
anyhow::Ok(with_parser(|parser| {
let mut store = parser.take_wasm_store().unwrap();
let grammar = store.load_language(grammar_name, &wasm_bytes);
@ -970,7 +968,7 @@ impl LanguageRegistry {
}
}
} else {
tx.send(Err(Arc::new(anyhow!("no such grammar {}", name))))
tx.send(Err(Arc::new(anyhow!("no such grammar {name}"))))
.ok();
}

View file

@ -1,7 +1,7 @@
//! Handles conversions of `language` items to and from the [`rpc`] protocol.
use crate::{CursorShape, Diagnostic, diagnostic_set::DiagnosticEntry};
use anyhow::{Context as _, Result, anyhow};
use anyhow::{Context as _, Result};
use clock::ReplicaId;
use lsp::{DiagnosticSeverity, LanguageServerId};
use rpc::proto;
@ -259,10 +259,7 @@ pub fn deserialize_anchor_range(range: proto::AnchorRange) -> Result<Range<Ancho
/// Deserializes an [`crate::Operation`] from the RPC representation.
pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operation> {
Ok(
match message
.variant
.ok_or_else(|| anyhow!("missing operation variant"))?
{
match message.variant.context("missing operation variant")? {
proto::operation::Variant::Edit(edit) => {
crate::Operation::Buffer(text::Operation::Edit(deserialize_edit_operation(edit)))
}
@ -312,7 +309,7 @@ pub fn deserialize_operation(message: proto::Operation) -> Result<crate::Operati
line_mode: message.line_mode,
cursor_shape: deserialize_cursor_shape(
proto::CursorShape::from_i32(message.cursor_shape)
.ok_or_else(|| anyhow!("Missing cursor shape"))?,
.context("Missing cursor shape")?,
),
}
}
@ -510,11 +507,7 @@ pub fn serialize_transaction(transaction: &Transaction) -> proto::Transaction {
/// Deserializes a [`Transaction`] from the RPC representation.
pub fn deserialize_transaction(transaction: proto::Transaction) -> Result<Transaction> {
Ok(Transaction {
id: deserialize_timestamp(
transaction
.id
.ok_or_else(|| anyhow!("missing transaction id"))?,
),
id: deserialize_timestamp(transaction.id.context("missing transaction id")?),
edit_ids: transaction
.edit_ids
.into_iter()

View file

@ -4,6 +4,7 @@ mod syntax_map_tests;
use crate::{
Grammar, InjectionConfig, Language, LanguageId, LanguageRegistry, QUERY_CURSORS, with_parser,
};
use anyhow::Context as _;
use collections::HashMap;
use futures::FutureExt;
use std::{
@ -1246,7 +1247,7 @@ fn parse_text(
old_tree.as_ref(),
None,
)
.ok_or_else(|| anyhow::anyhow!("failed to parse"))
.context("failed to parse")
})
}