mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 14:44:12 +00:00
improve macro ergonomics
This commit is contained in:
parent
1f68399e7b
commit
502d670dff
4 changed files with 32 additions and 53 deletions
|
@ -9,7 +9,6 @@ pub struct LayoutId(pub usize);
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Layout {
|
||||
pub layout_name: Ident,
|
||||
pub comp: Ident,
|
||||
pub props_name: Ident,
|
||||
pub active_nests: Vec<NestId>,
|
||||
|
@ -37,10 +36,6 @@ impl Layout {
|
|||
|
||||
impl Layout {
|
||||
pub fn parse(input: syn::parse::ParseStream, active_nests: Vec<NestId>) -> syn::Result<Self> {
|
||||
// Then parse the layout name
|
||||
let _ = input.parse::<syn::Token![,]>();
|
||||
let layout_name: syn::Ident = input.parse()?;
|
||||
|
||||
// Then parse the component name
|
||||
let _ = input.parse::<syn::Token![,]>();
|
||||
let comp: Ident = input.parse()?;
|
||||
|
@ -52,7 +47,6 @@ impl Layout {
|
|||
.unwrap_or_else(|_| format_ident!("{}Props", comp.to_string()));
|
||||
|
||||
Ok(Self {
|
||||
layout_name,
|
||||
comp,
|
||||
props_name,
|
||||
active_nests,
|
||||
|
|
|
@ -5,7 +5,7 @@ use nest::{Nest, NestId};
|
|||
use proc_macro::TokenStream;
|
||||
use quote::{__private::Span, format_ident, quote, ToTokens};
|
||||
use route::Route;
|
||||
use syn::{parse::ParseStream, parse_macro_input, Ident};
|
||||
use syn::{parse::ParseStream, parse_macro_input, Ident, Token};
|
||||
|
||||
use proc_macro2::TokenStream as TokenStream2;
|
||||
|
||||
|
@ -18,9 +18,8 @@ mod route;
|
|||
mod route_tree;
|
||||
mod segment;
|
||||
|
||||
// #[proc_macro_derive(Routable, attributes(route, nest, end_nest))]
|
||||
#[proc_macro_attribute]
|
||||
pub fn routable(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
#[proc_macro_derive(Routable, attributes(route, nest, end_nest, layout, end_layout))]
|
||||
pub fn routable(input: TokenStream) -> TokenStream {
|
||||
let routes_enum = parse_macro_input!(input as syn::ItemEnum);
|
||||
|
||||
let route_enum = match RouteEnum::parse(routes_enum) {
|
||||
|
@ -48,8 +47,6 @@ pub fn routable(_: TokenStream, input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
struct RouteEnum {
|
||||
attrs: Vec<syn::Attribute>,
|
||||
vis: syn::Visibility,
|
||||
name: Ident,
|
||||
routes: Vec<Route>,
|
||||
nests: Vec<Nest>,
|
||||
|
@ -62,13 +59,14 @@ impl RouteEnum {
|
|||
|
||||
let mut routes = Vec::new();
|
||||
|
||||
let mut layouts = Vec::new();
|
||||
let mut layouts: Vec<Layout> = Vec::new();
|
||||
let mut layout_stack = Vec::new();
|
||||
|
||||
let mut nests = Vec::new();
|
||||
let mut nest_stack = Vec::new();
|
||||
|
||||
for variant in &data.variants {
|
||||
let mut excluded = Vec::new();
|
||||
// Apply the any nesting attributes in order
|
||||
for attr in &variant.attrs {
|
||||
if attr.path.is_ident("nest") {
|
||||
|
@ -113,15 +111,31 @@ impl RouteEnum {
|
|||
} else if attr.path.is_ident("end_nest") {
|
||||
nest_stack.pop();
|
||||
} else if attr.path.is_ident("layout") {
|
||||
let layout_index = layouts.len();
|
||||
|
||||
let parser = |input: ParseStream| {
|
||||
Layout::parse(input, nest_stack.iter().rev().cloned().collect())
|
||||
let bang: Option<Token![!]> = input.parse().ok();
|
||||
let exclude = bang.is_some();
|
||||
Ok((
|
||||
exclude,
|
||||
Layout::parse(input, nest_stack.iter().rev().cloned().collect())?,
|
||||
))
|
||||
};
|
||||
let layout = attr.parse_args_with(parser)?;
|
||||
let (exclude, layout): (bool, Layout) = attr.parse_args_with(parser)?;
|
||||
|
||||
layouts.push(layout);
|
||||
layout_stack.push(LayoutId(layout_index));
|
||||
if exclude {
|
||||
let Some(layout_index) =
|
||||
layouts.iter().position(|l| l.comp == layout.comp)else{
|
||||
return Err(syn::Error::new(
|
||||
Span::call_site(),
|
||||
"Attempted to exclude a layout that does not exist",
|
||||
));
|
||||
}
|
||||
;
|
||||
excluded.push(LayoutId(layout_index));
|
||||
} else {
|
||||
let layout_index = layouts.len();
|
||||
layouts.push(layout);
|
||||
layout_stack.push(LayoutId(layout_index));
|
||||
}
|
||||
} else if attr.path.is_ident("end_layout") {
|
||||
layout_stack.pop();
|
||||
}
|
||||
|
@ -130,6 +144,7 @@ impl RouteEnum {
|
|||
let mut active_nests = nest_stack.clone();
|
||||
active_nests.reverse();
|
||||
let mut active_layouts = layout_stack.clone();
|
||||
active_layouts.retain(|&id| !excluded.contains(&id));
|
||||
active_layouts.reverse();
|
||||
|
||||
let route = Route::parse(active_nests, active_layouts, variant.clone())?;
|
||||
|
@ -139,8 +154,6 @@ impl RouteEnum {
|
|||
|
||||
let myself = Self {
|
||||
name: name.clone(),
|
||||
attrs: data.attrs,
|
||||
vis: data.vis,
|
||||
routes,
|
||||
nests,
|
||||
layouts,
|
||||
|
@ -315,16 +328,8 @@ impl RouteEnum {
|
|||
impl ToTokens for RouteEnum {
|
||||
fn to_tokens(&self, tokens: &mut quote::__private::TokenStream) {
|
||||
let routes = &self.routes;
|
||||
let vis = &self.vis;
|
||||
let name = &self.name;
|
||||
let attrs = &self.attrs;
|
||||
let variants = routes.iter().map(|r| r.variant());
|
||||
|
||||
tokens.extend(quote!(
|
||||
#(#attrs)*
|
||||
#vis enum #name {
|
||||
#(#variants),*
|
||||
}
|
||||
|
||||
#[path = "pages"]
|
||||
mod pages {
|
||||
|
|
|
@ -186,13 +186,10 @@ impl Route {
|
|||
}
|
||||
}
|
||||
for segment in &self.segments {
|
||||
match segment {
|
||||
RouteSegment::Dynamic(name, _) => {
|
||||
if name == f.ident.as_ref().unwrap() {
|
||||
from_route = true
|
||||
}
|
||||
if let RouteSegment::Dynamic(name, ..) = segment {
|
||||
if name == f.ident.as_ref().unwrap() {
|
||||
from_route = true
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,23 +270,6 @@ impl Route {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn variant(&self) -> TokenStream2 {
|
||||
let name = &self.route_name;
|
||||
let fields = self.fields.named.iter().map(|f| {
|
||||
let mut new = f.clone();
|
||||
new.attrs.retain(|a| {
|
||||
!a.path.is_ident("nest")
|
||||
&& !a.path.is_ident("end_nest")
|
||||
&& !a.path.is_ident("layout")
|
||||
&& !a.path.is_ident("end_layout")
|
||||
});
|
||||
new
|
||||
});
|
||||
|
||||
quote! {
|
||||
#name { #(#fields,)* }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for Route {
|
||||
|
|
|
@ -48,7 +48,7 @@ pub mod prelude {
|
|||
pub use crate::contexts::*;
|
||||
pub use crate::hooks::*;
|
||||
pub use crate::router_cfg::RouterConfiguration;
|
||||
pub use dioxus_router_macro::routable;
|
||||
pub use dioxus_router_macro::Routable;
|
||||
}
|
||||
|
||||
mod utils {
|
||||
|
|
Loading…
Reference in a new issue