yeast: Make transforms return Result

This will enable us to actually capture and log errors in complicated
rules (e.g. ones written in Rust) rather than just panicking.
This commit is contained in:
Taus
2026-06-24 14:08:32 +00:00
parent d6373eaef7
commit d38ffe0ad5
2 changed files with 9 additions and 6 deletions

View File

@@ -891,7 +891,8 @@ pub fn parse_rule_top(input: TokenStream) -> Result<TokenStream> {
yeast::Rule::new(__query, Box::new(|__ast: &mut yeast::Ast, __captures: yeast::captures::Captures, __fresh: &yeast::tree_builder::FreshScope, __source_range: Option<tree_sitter::Range>, __user_ctx: &mut _| {
#(#bindings)*
let mut #ctx_ident = yeast::build::BuildCtx::with_source_range(__ast, &__captures, __fresh, __source_range, __user_ctx);
#transform_body
let __result: Vec<usize> = { #transform_body };
Ok(__result)
}))
}
})

View File

@@ -703,7 +703,9 @@ impl From<tree_sitter::Range> for NodeContent {
/// The transform function for a rule: takes the AST, captured variables, a
/// fresh-name scope, the source range of the matched node, and a mutable
/// reference to the user context of type `C`. Returns the IDs of the
/// replacement nodes.
/// replacement nodes, or an error message if the transform could not be
/// completed (for example, a required capture was missing, or a recursive
/// translation invoked by the transform failed).
pub type Transform<C = ()> = Box<
dyn Fn(
&mut Ast,
@@ -711,7 +713,7 @@ pub type Transform<C = ()> = Box<
&tree_builder::FreshScope,
Option<tree_sitter::Range>,
&mut C,
) -> Vec<Id>
) -> Result<Vec<Id>, String>
+ Send
+ Sync,
>;
@@ -752,7 +754,7 @@ impl<C> Rule<C> {
user_ctx: &mut C,
) -> Result<Option<Vec<Id>>, String> {
match self.try_match(ast, node)? {
Some(captures) => Ok(Some(self.run_transform(ast, captures, node, fresh, user_ctx))),
Some(captures) => Ok(Some(self.run_transform(ast, captures, node, fresh, user_ctx)?)),
None => Ok(None),
}
}
@@ -777,7 +779,7 @@ impl<C> Rule<C> {
node: Id,
fresh: &tree_builder::FreshScope,
user_ctx: &mut C,
) -> Vec<Id> {
) -> Result<Vec<Id>, String> {
fresh.next_scope();
let source_range = ast.get_node(node).and_then(|n| match n.content {
NodeContent::Range(r) => Some(r),
@@ -974,7 +976,7 @@ fn apply_one_shot_rules_inner<C: Clone>(
}
apply_one_shot_rules_inner(index, ast, user_ctx, captured_id, fresh, rewrite_depth + 1)
})?;
let result = rule.run_transform(ast, captures, id, fresh, user_ctx);
let result = rule.run_transform(ast, captures, id, fresh, user_ctx)?;
*user_ctx = snapshot;
return Ok(result);
}