use proc_macro2::{Span, TokenStream as TokenStream2};
use quote::ToTokens;
use std::{cell::Cell, fmt::Debug};
use syn::{
parse::{Parse, ParseStream},
Result,
};
use crate::{BodyNode, TemplateBody};
#[derive(Debug, Clone)]
pub struct CallBody {
pub body: TemplateBody,
pub template_idx: Cell<usize>,
pub span: Option<Span>,
}
impl Parse for CallBody {
fn parse(input: ParseStream) -> Result<Self> {
let mut body = CallBody::new(input.parse()?);
body.span = Some(input.span());
Ok(body)
}
}
impl ToTokens for CallBody {
fn to_tokens(&self, out: &mut TokenStream2) {
self.body.to_tokens(out)
}
}
impl CallBody {
pub fn new(body: TemplateBody) -> Self {
let body = CallBody {
body,
template_idx: Cell::new(0),
span: None,
};
body.body.template_idx.set(body.next_template_idx());
body.cascade_hotreload_info(&body.body.roots);
body
}
pub fn parse_strict(input: ParseStream) -> Result<Self> {
Self::parse(input)
}
fn cascade_hotreload_info(&self, nodes: &[BodyNode]) {
for node in nodes.iter() {
match node {
BodyNode::Element(el) => {
self.cascade_hotreload_info(&el.children);
}
BodyNode::Component(comp) => {
comp.children.template_idx.set(self.next_template_idx());
self.cascade_hotreload_info(&comp.children.roots);
}
BodyNode::ForLoop(floop) => {
floop.body.template_idx.set(self.next_template_idx());
self.cascade_hotreload_info(&floop.body.roots);
}
BodyNode::IfChain(chain) => chain.for_each_branch(&mut |body| {
body.template_idx.set(self.next_template_idx());
self.cascade_hotreload_info(&body.roots)
}),
_ => {}
}
}
}
fn next_template_idx(&self) -> usize {
let idx = self.template_idx.get();
self.template_idx.set(idx + 1);
idx
}
}