Compare commits
10
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6cf2be0ed | ||
|
|
d28bd2fdef | ||
|
|
2d93b82802 | ||
|
|
be9b3cc0df | ||
|
|
a5f018d0a8 | ||
|
|
cee73fb885 | ||
|
|
2f1f2b3395 | ||
|
|
2d0668955e | ||
|
|
8550b5f6ff | ||
|
|
8bb0116c1d |
+5
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "osui-element"
|
name = "osui-element"
|
||||||
version = "0.1.14"
|
version = "0.1.23"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "The element attribute for defining elements in OSUI"
|
description = "The element attribute for defining elements in OSUI"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
@@ -9,6 +9,10 @@ license = "Apache-2.0"
|
|||||||
proc-macro = true
|
proc-macro = true
|
||||||
path = "./lib.rs"
|
path = "./lib.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
path = "./main.rs"
|
||||||
|
name = "osui-element"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
proc-macro2 = "1.0.89"
|
proc-macro2 = "1.0.89"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::Parser, parse_macro_input, DeriveInput, Fields, GenericParam, Lifetime, LifetimeParam,
|
parse::Parser, parse_macro_input, DeriveInput, FnArg, GenericParam, ItemFn, Lifetime,
|
||||||
|
LifetimeParam, PatIdent, PatType,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@@ -16,16 +17,15 @@ pub fn element(_args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
if ast.generics.lifetimes().count() == 0 && !has_generics {
|
if ast.generics.lifetimes().count() == 0 && !has_generics {
|
||||||
ast.generics
|
ast.generics
|
||||||
.params
|
.params
|
||||||
.push(GenericParam::Lifetime(LifetimeParam::new(Lifetime::new(
|
.push(syn::GenericParam::Lifetime(LifetimeParam::new(
|
||||||
"'a",
|
Lifetime::new("'a", proc_macro2::Span::call_site()),
|
||||||
proc_macro2::Span::call_site(),
|
)));
|
||||||
))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify the struct fields to include additional fields
|
// Modify the struct fields to include additional fields
|
||||||
match &mut ast.data {
|
match &mut ast.data {
|
||||||
syn::Data::Struct(ref mut struct_data) => {
|
syn::Data::Struct(ref mut struct_data) => {
|
||||||
if let Fields::Named(fields) = &mut struct_data.fields {
|
if let syn::Fields::Named(fields) = &mut struct_data.fields {
|
||||||
fields.named.push(
|
fields.named.push(
|
||||||
syn::Field::parse_named
|
syn::Field::parse_named
|
||||||
.parse2(quote! { pub children: Children })
|
.parse2(quote! { pub children: Children })
|
||||||
@@ -90,25 +90,57 @@ pub fn element(_args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn elem_fn(_args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn component(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let input_fn = parse_macro_input!(input as ItemFn);
|
||||||
let struct_name = &ast.ident;
|
|
||||||
|
|
||||||
let func_name = syn::Ident::new(
|
let fn_name = input_fn.sig.ident.clone();
|
||||||
&struct_name.to_string().to_lowercase(),
|
let code = input_fn.block;
|
||||||
proc_macro2::Span::call_site(),
|
let visibility = input_fn.vis;
|
||||||
);
|
let return_type = match input_fn.sig.output {
|
||||||
|
syn::ReturnType::Default => syn::parse_quote! { Element },
|
||||||
|
syn::ReturnType::Type(_, t) => t,
|
||||||
|
};
|
||||||
|
|
||||||
let elem_fn = quote! {
|
let lifetimes: Vec<_> = input_fn
|
||||||
pub fn #func_name<'a>() -> Box<#struct_name<'a>> {
|
.sig
|
||||||
Box::new(#struct_name::default())
|
.generics
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.filter_map(|param| {
|
||||||
|
if let GenericParam::Lifetime(lifetime) = param {
|
||||||
|
Some(&lifetime.lifetime)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let mut struct_fields = Vec::new();
|
||||||
|
|
||||||
|
for arg in input_fn.sig.inputs.iter() {
|
||||||
|
if let FnArg::Typed(PatType { pat, ty, .. }) = arg {
|
||||||
|
if let syn::Pat::Ident(PatIdent { ident, .. }) = &**pat {
|
||||||
|
let field_name = ident.clone();
|
||||||
|
let field_type = ty.clone();
|
||||||
|
struct_fields.push(quote! { pub #field_name: #field_type });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
#visibility struct #fn_name<#(#lifetimes),*> {
|
||||||
|
#(#struct_fields),*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <#(#lifetimes),*> Component for #fn_name <#(#lifetimes),*> {
|
||||||
|
type Element = #return_type;
|
||||||
|
fn create_element(self) -> Self::Element {
|
||||||
|
#code
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let expanded = quote! {
|
TokenStream::from(expanded)
|
||||||
#ast
|
|
||||||
#elem_fn
|
|
||||||
};
|
|
||||||
|
|
||||||
expanded.into()
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user