seperate dynamic nested segments and layouts

This commit is contained in:
Evan Almloff committed 2023-05-22 11:44:24 -05:00
1 parent be3dae4b05
commit ef6551a6cd
7 files changed
+294 -330

No files matched your search

+46 -96
View File
@@ -1,83 +1,55 @@
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::{parse::Parse, Ident, LitStr};
use syn::{Ident, LitStr};
use crate::segment::{parse_route_segments, RouteSegment};
pub enum Nest {
Static(String),
Layout(Layout),
}
#[derive(Debug, Clone, Copy)]
pub struct NestId(pub usize);
impl Parse for Nest {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
// First parse the route
let route: LitStr = input.parse()?;
let is_dynamic = route.value().contains('(');
if !input.is_empty() || is_dynamic {
// Then parse the layout name
let _ = input.parse::<syn::Token![,]>();
let layout_name: syn::Ident = input.parse()?;
let layout_fields: syn::FieldsNamed = input.parse()?;
// Then parse the component name
let _ = input.parse::<syn::Token![,]>();
let comp: Ident = input.parse()?;
// Then parse the props name
let _ = input.parse::<syn::Token![,]>();
let props_name: Ident = input
.parse()
.unwrap_or_else(|_| format_ident!("{}Props", comp.to_string()));
let route_segments =
parse_route_segments(&layout_name, &layout_fields, &route.value())?.0;
for seg in &route_segments {
if let RouteSegment::CatchAll(name, _) = seg {
return Err(syn::Error::new_spanned(
name,
format!(
"Catch-all segments are not allowed in nested routes: {}",
route.value()
),
));
}
}
Ok(Self::Layout(Layout {
route: route.value(),
segments: route_segments,
layout_name,
comp,
props_name,
layout_fields,
}))
} else {
Ok(Self::Static(route.value()))
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct LayoutId(pub usize);
#[derive(Debug)]
pub struct Layout {
#[derive(Debug, Clone)]
pub struct Nest {
pub route: String,
pub segments: Vec<RouteSegment>,
pub layout_name: Ident,
pub layout_fields: syn::FieldsNamed,
pub comp: Ident,
pub props_name: Ident,
index: usize,
}
impl Layout {
pub fn add_static_prefix(&mut self, prefix: &str) {
self.route = format!("{}{}", prefix, self.route);
self.segments.push(RouteSegment::Static(prefix.to_string()));
}
impl Nest {
pub fn parse(
input: syn::parse::ParseStream,
children_routes: Vec<syn::FieldsNamed>,
index: usize,
) -> syn::Result<Self> {
// Parse the route
let route: LitStr = input.parse()?;
let route_segments = parse_route_segments(
route.span(),
children_routes.iter().flat_map(|f| f.named.iter()),
&route.value(),
)?
.0;
for seg in &route_segments {
if let RouteSegment::CatchAll(name, _) = seg {
return Err(syn::Error::new_spanned(
name,
format!(
"Catch-all segments are not allowed in nested routes: {}",
route.value()
),
));
}
}
Ok(Self {
route: route.value(),
segments: route_segments,
index,
})
}
}
impl Nest {
pub fn dynamic_segments(&self) -> impl Iterator<Item = TokenStream> + '_ {
self.segments
.iter()
@@ -85,13 +57,6 @@ impl Layout {
.map(|i| quote! {#i})
}
pub fn dynamic_segment_types(&self) -> impl Iterator<Item = TokenStream> + '_ {
self.segments
.iter()
.filter_map(|seg| seg.ty())
.map(|ty| quote! {#ty})
}
pub fn write(&self) -> TokenStream {
let write_segments = self.segments.iter().map(|s| s.write_segment());
@@ -103,7 +68,11 @@ impl Layout {
}
pub fn error_ident(&self) -> Ident {
format_ident!("{}LayoutParseError", self.layout_name)
format_ident!("Nest{}ParseError", self.index)
}
pub fn error_variant(&self) -> Ident {
format_ident!("Nest{}", self.index)
}
pub fn error_type(&self) -> TokenStream {
@@ -147,23 +116,4 @@ impl Layout {
}
}
}
pub fn routable_match(&self) -> TokenStream {
let props_name = &self.props_name;
let comp_name = &self.comp;
let dynamic_segments_from_route = self
.segments
.iter()
.filter_map(|seg| seg.name())
.map(|seg| quote! { #seg });
quote! {
let comp = #props_name { #(#dynamic_segments_from_route,)* };
let cx = cx.bump().alloc(Scoped {
props: cx.bump().alloc(comp),
scope: cx,
});
#comp_name(cx)
}
}
}