Skip to content

Commit e3b3888

Browse files
committed
Yeast: Fix handling of captures with multiple results
1 parent ef9306d commit e3b3888

2 files changed

Lines changed: 20 additions & 15 deletions

File tree

shared/yeast/src/captures.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,20 @@ impl Captures {
6363
}
6464

6565
/// Apply a fallible function to every captured id (across all keys),
66-
/// replacing each id with the result. Stops and returns the error on
67-
/// the first failure.
66+
/// replacing each id with the results. A function returning an empty
67+
/// vector removes the capture; returning multiple ids splices them
68+
/// into the capture's value list (suitable for `*`/`+` captures).
69+
/// Stops and returns the error on the first failure.
6870
pub fn try_map_all_captures<E>(
6971
&mut self,
70-
mut f: impl FnMut(Id) -> Result<Id, E>,
72+
mut f: impl FnMut(Id) -> Result<Vec<Id>, E>,
7173
) -> Result<(), E> {
7274
for ids in self.captures.values_mut() {
73-
for id in ids {
74-
*id = f(*id)?;
75+
let mut new_ids = Vec::with_capacity(ids.len());
76+
for &id in ids.iter() {
77+
new_ids.extend(f(id)?);
7578
}
79+
*ids = new_ids;
7680
}
7781
Ok(())
7882
}

shared/yeast/src/lib.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,15 @@ impl Node {
563563
NodeContent::DynamicString(s) => Some(s.to_string()),
564564
}
565565
}
566+
567+
/// Read the child ids stored under a given field, or an empty slice if
568+
/// no such field is present on this node.
569+
pub fn field_children(&self, field_id: FieldId) -> &[Id] {
570+
self.fields
571+
.get(&field_id)
572+
.map(|v| v.as_slice())
573+
.unwrap_or(&[])
574+
}
566575
}
567576

568577
/// The contents of a node is either a range in the original source file,
@@ -836,17 +845,9 @@ fn apply_one_shot_rules_inner(
836845
// pattern root): re-analyzing it would match the same rule
837846
// again indefinitely.
838847
if captured_id == id {
839-
return Ok(captured_id);
840-
}
841-
let result =
842-
apply_one_shot_rules_inner(index, ast, captured_id, fresh, rewrite_depth + 1)?;
843-
if result.len() != 1 {
844-
return Err(format!(
845-
"OneShot: recursion on captured node produced {} results, expected exactly 1",
846-
result.len()
847-
));
848+
return Ok(vec![captured_id]);
848849
}
849-
Ok(result[0])
850+
apply_one_shot_rules_inner(index, ast, captured_id, fresh, rewrite_depth + 1)
850851
})?;
851852
return Ok(rule.run_transform(ast, captures, id, fresh));
852853
}

0 commit comments

Comments
 (0)