use syn::{
parse_quote,
visit_mut::{visit_expr_break_mut, visit_expr_mut, visit_item_mut, VisitMut},
Label,
};
pub struct BreakVisitor<'f> {
pub label: &'f Option<Label>,
pub outside: bool,
pub breaks: usize,
}
impl<'f> VisitMut for BreakVisitor<'f> {
fn visit_expr_break_mut(&mut self, i: &mut syn::ExprBreak) {
visit_expr_break_mut(self, i);
if !self.outside || i.label
.as_ref()
.zip(self.label.as_ref())
.map_or(false, |(a, b)| *a == b.name)
{
self.breaks += 1;
let expr = i.expr.get_or_insert_with(|| Box::new(parse_quote! { () }));
*expr = parse_quote! { ::jenner::ForResult::Break(#expr) };
}
}
fn visit_expr_mut(&mut self, i: &mut syn::Expr) {
match i {
syn::Expr::Closure(_) => {}
syn::Expr::ForLoop(_) | syn::Expr::Loop(_) | syn::Expr::While(_) => {
let store = self.outside;
self.outside = true;
visit_expr_mut(self, i);
self.outside = store;
}
i => visit_expr_mut(self, i),
}
}
fn visit_item_mut(&mut self, i: &mut syn::Item) {
match i {
syn::Item::Fn(_)
| syn::Item::ForeignMod(_)
| syn::Item::Impl(_)
| syn::Item::Macro(_)
| syn::Item::Macro2(_)
| syn::Item::Mod(_)
| syn::Item::Trait(_) => {}
i => visit_item_mut(self, i),
}
}
}