-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
250 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,3 +48,6 @@ features = [ | |
"CssStyleDeclaration", | ||
] | ||
version = "^0.3" | ||
|
||
[dev-dependencies] | ||
wasm-bindgen-test = "^0.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
use proc_macro2::TokenStream; | ||
use quote::quote; | ||
use syn::parse::{Parse, ParseStream}; | ||
use syn::spanned::Spanned; | ||
use syn::{Data, DeriveInput, Ident}; | ||
|
||
pub struct DeriveApp { | ||
ident: Ident, | ||
} | ||
|
||
impl Parse for DeriveApp { | ||
fn parse(input: ParseStream) -> syn::Result<Self> { | ||
let DeriveInput { ident, data, .. } = input.parse()?; | ||
|
||
match data { | ||
Data::Enum(e) => { | ||
return Err(syn::Error::new( | ||
e.enum_token.span(), | ||
"expected struct, found enum", | ||
)) | ||
} | ||
Data::Struct(data) => data, | ||
Data::Union(u) => { | ||
return Err(syn::Error::new( | ||
u.union_token.span(), | ||
"expected enum, found union", | ||
)) | ||
} | ||
}; | ||
|
||
Ok(Self { ident }) | ||
} | ||
} | ||
|
||
pub fn root(input: DeriveApp) -> TokenStream { | ||
let DeriveApp { ident, .. } = &input; | ||
|
||
quote! { | ||
#[automatically_derived] | ||
impl ::hikari_boot::Application for #ident { | ||
#[allow(bindings_with_variant_name)] | ||
fn switch() -> ::yew::Html { | ||
todo!("implement switch") | ||
} | ||
|
||
fn App() -> yew::Html { | ||
todo!("implement App") | ||
} | ||
|
||
fn ServerApp( | ||
url: &String, | ||
props: &::hikari_boot::AppContext<<Self as ::hikari_boot::Application>::AppProps> | ||
) -> yew::Html { | ||
todo!("implement ServerApp") | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,124 @@ | ||
use std::collections::HashMap; | ||
|
||
use proc_macro2::TokenStream; | ||
use quote::quote; | ||
use syn::parse::{Parse, ParseStream}; | ||
use syn::{DeriveInput, Ident}; | ||
use syn::{ | ||
parse::{Parse, ParseStream}, | ||
punctuated::Punctuated, | ||
spanned::Spanned, | ||
Data, DeriveInput, Fields, Ident, Path, Type, Variant, | ||
}; | ||
|
||
const COMPONENT_ATTR_IDENT: &str = "component"; | ||
|
||
#[derive(Debug, Clone, PartialEq)] | ||
pub struct Component { | ||
component: Path, | ||
props: Option<Type>, | ||
} | ||
|
||
pub type Components = HashMap<Ident, Component>; | ||
|
||
pub struct DeriveAppProps { | ||
ident: Ident, | ||
components: Components, | ||
} | ||
|
||
impl Parse for DeriveAppProps { | ||
fn parse(input: ParseStream) -> syn::Result<Self> { | ||
let DeriveInput { ident, .. } = input.parse()?; | ||
let DeriveInput { ident, data, .. } = input.parse()?; | ||
|
||
let data = match data { | ||
Data::Enum(data) => data, | ||
Data::Struct(s) => { | ||
return Err(syn::Error::new( | ||
s.struct_token.span(), | ||
"expected enum, found struct", | ||
)) | ||
} | ||
Data::Union(u) => { | ||
return Err(syn::Error::new( | ||
u.union_token.span(), | ||
"expected enum, found union", | ||
)) | ||
} | ||
}; | ||
|
||
let components = parse_variants_attributes(&data.variants)?; | ||
|
||
Ok(Self { ident, components }) | ||
} | ||
} | ||
|
||
fn parse_variants_attributes( | ||
variants: &Punctuated<Variant, syn::token::Comma>, | ||
) -> syn::Result<Components> { | ||
let mut components: Components = Default::default(); | ||
|
||
for variant in variants.iter() { | ||
let attrs = &variant.attrs; | ||
let at_attrs = attrs | ||
.iter() | ||
.filter(|attr| attr.path().is_ident(COMPONENT_ATTR_IDENT)) | ||
.collect::<Vec<_>>(); | ||
|
||
Ok(Self { ident }) | ||
let attr = match at_attrs.len() { | ||
1 => *at_attrs.first().unwrap(), | ||
0 => { | ||
return Err(syn::Error::new( | ||
variant.span(), | ||
format!("{COMPONENT_ATTR_IDENT} attribute must be present on every variant"), | ||
)) | ||
} | ||
_ => { | ||
return Err(syn::Error::new_spanned( | ||
quote! { #(#at_attrs)* }, | ||
format!("only one {COMPONENT_ATTR_IDENT} attribute must be present"), | ||
)) | ||
} | ||
}; | ||
|
||
let component_path = attr.parse_args::<Path>()?; | ||
|
||
let field = match &variant.fields { | ||
Fields::Named(ref field) => { | ||
return Err(syn::Error::new( | ||
field.span(), | ||
"only unnamed fields are supported", | ||
)); | ||
} | ||
Fields::Unnamed(ref fields) => { | ||
if fields.unnamed.len() > 1 { | ||
return Err(syn::Error::new( | ||
fields.span(), | ||
"only one field is supported", | ||
)); | ||
} | ||
Some(fields.unnamed.first().unwrap().ty.clone()) | ||
} | ||
Fields::Unit => None, | ||
}; | ||
|
||
components.insert( | ||
variant.ident.clone(), | ||
Component { | ||
component: component_path, | ||
props: field, | ||
}, | ||
); | ||
} | ||
|
||
Ok(components) | ||
} | ||
|
||
pub fn root(input: DeriveAppProps) -> TokenStream { | ||
let DeriveAppProps { ident, .. } = &input; | ||
let DeriveAppProps { | ||
components, ident, .. | ||
} = &input; | ||
|
||
quote! { | ||
#[automatically_derived] | ||
impl ::hikari_boot::DeriveAppPropsTrait for #ident { | ||
type AppProps = Self; | ||
impl ::hikari_boot::AppProps for #ident { | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.