use quote::{ToTokens, quote};
use syn::{
LitStr, Token,
parse::Parse,
punctuated::Punctuated,
token::{Brace, Comma},
};
use crate::element::ParsedElementHead;
pub struct ParsedRoute {
pub path: LitStr,
pub element: ParsedElementHead,
pub children: Routes,
}
#[derive(Default)]
pub struct Routes(pub Punctuated<ParsedRoute, Comma>);
impl Parse for ParsedRoute {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let path: LitStr = input.parse()?;
input.parse::<Token![=>]>()?;
let element = input.parse::<ParsedElementHead>()?;
if let Some(span) = element.key_span() {
return Err(syn::Error::new(
span,
"路由组件不支持 `key:`,路由身份由 path 决定",
));
}
let mut children = Routes::default();
if input.peek(Brace) {
let children_input;
syn::braced!(children_input in input);
children = children_input.parse()?;
}
Ok(ParsedRoute {
path,
element,
children,
})
}
}
impl Parse for Routes {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let routes = Punctuated::parse_terminated(input)?;
Ok(Routes(routes))
}
}
impl ToTokens for ParsedRoute {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let path = &self.path;
let children = &self.children;
let element = self.element.to_element_expr(&[]);
tokens.extend(quote! {
::ratatui_kit::components::Route::new(
#path.to_string(),
#element.into_any(),
#children.into(),
)
});
}
}
impl ToTokens for Routes {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let routes = self.0.iter().map(|route| route.to_token_stream());
tokens.extend(quote! {
vec![
#(#routes),*
]
});
}
}