Element refinement passing on ui2

This commit is contained in:
Nathan Sobo 2023-11-18 20:05:47 -07:00
parent be33f000e2
commit adc355a1e6
87 changed files with 2066 additions and 1372 deletions

View file

@ -1,75 +0,0 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, GenericParam};
pub fn derive_element(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let type_name = ast.ident;
let mut view_state_ty = quote! { V };
for param in &ast.generics.params {
if let GenericParam::Type(type_param) = param {
let type_ident = &type_param.ident;
view_state_ty = quote! {#type_ident};
break;
}
}
let attrs = &ast.attrs;
for attr in attrs {
if attr.path.is_ident("element") {
match attr.parse_meta() {
Ok(syn::Meta::List(i)) => {
for nested_meta in i.nested {
if let syn::NestedMeta::Meta(syn::Meta::NameValue(nv)) = nested_meta {
if nv.path.is_ident("view_state") {
if let syn::Lit::Str(lit_str) = nv.lit {
view_state_ty = lit_str.value().parse().unwrap();
}
}
}
}
}
_ => (),
}
}
}
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let gen = quote! {
impl #impl_generics gpui::Element<#view_state_ty> for #type_name #ty_generics
#where_clause
{
type State = Option<gpui::AnyElement<#view_state_ty>>;
fn element_id(&self) -> Option<gpui::ElementId> {
None
}
fn layout(
&mut self,
view_state: &mut #view_state_ty,
_element_state: Option<Self::State>,
cx: &mut gpui::ViewContext<#view_state_ty>,
) -> (gpui::LayoutId, Self::State) {
let mut element = self.render(view_state, cx).into_any();
let layout_id = element.layout(view_state, cx);
(layout_id, Some(element))
}
fn paint(
self,
_bounds: gpui::Bounds<gpui::Pixels>,
view_state: &mut #view_state_ty,
rendered_element: &mut Self::State,
cx: &mut gpui::ViewContext<#view_state_ty>,
) {
rendered_element.take().unwrap().paint(view_state, cx)
}
}
};
gen.into()
}

View file

@ -0,0 +1,64 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput};
pub fn derive_render_once(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let type_name = &ast.ident;
let mut trait_generics = ast.generics.clone();
let view_type = if let Some(view_type) = specified_view_type(&ast) {
quote! { #view_type }
} else {
if let Some(first_type_param) = ast.generics.params.iter().find_map(|param| {
if let syn::GenericParam::Type(type_param) = param {
Some(type_param.ident.clone())
} else {
None
}
}) {
quote! { #first_type_param }
} else {
trait_generics.params.push(parse_quote! { V: 'static });
quote! { V }
}
};
let (impl_generics, _, where_clause) = trait_generics.split_for_impl();
let (_, type_generics, _) = ast.generics.split_for_impl();
let gen = quote! {
impl #impl_generics gpui::RenderOnce<#view_type> for #type_name #type_generics
#where_clause
{
type Element = gpui::CompositeElement<#view_type, Self>;
fn render_once(self) -> Self::Element {
gpui::CompositeElement::new(self)
}
}
};
if type_name == "Avatar" {
println!("{gen}");
}
gen.into()
}
fn specified_view_type(ast: &DeriveInput) -> Option<proc_macro2::Ident> {
ast.attrs.iter().find_map(|attr| {
if attr.path.is_ident("view") {
if let Ok(syn::Meta::NameValue(meta_name_value)) = attr.parse_meta() {
if let syn::Lit::Str(lit_str) = meta_name_value.lit {
return Some(
lit_str
.parse::<syn::Ident>()
.expect("Failed to parse view_type"),
);
}
}
}
None
})
}

View file

@ -1,6 +1,6 @@
mod action;
mod derive_component;
mod derive_element;
mod derive_render_once;
mod register_action;
mod style_helpers;
mod test;
@ -22,9 +22,9 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
derive_component::derive_component(input)
}
#[proc_macro_derive(Element, attributes(element))]
pub fn derive_element(input: TokenStream) -> TokenStream {
derive_element::derive_element(input)
#[proc_macro_derive(RenderOnce, attributes(view))]
pub fn derive_render_once(input: TokenStream) -> TokenStream {
derive_render_once::derive_render_once(input)
}
#[proc_macro]