Add derive macro for IntoAnyElement

This commit is contained in:
Nathan Sobo 2023-10-26 12:20:46 +02:00
parent 927278e20d
commit 315744ec20
4 changed files with 79 additions and 9 deletions

View file

@ -0,0 +1,54 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};
pub fn derive_into_any_element(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let generics = &ast.generics;
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let specified_view_type = ast
.attrs
.iter()
.find(|attr| attr.path.is_ident("element"))
.and_then(|attr| {
if let Ok(syn::Meta::List(meta_list)) = attr.parse_meta() {
meta_list.nested.iter().find_map(|nested| {
if let syn::NestedMeta::Meta(syn::Meta::NameValue(nv)) = nested {
if nv.path.is_ident("view_type") {
if let syn::Lit::Str(lit_str) = &nv.lit {
return Some(
lit_str
.parse::<syn::Ident>()
.expect("Failed to parse view_type"),
);
}
}
}
None
})
} else {
None
}
});
let view_type = specified_view_type.unwrap_or_else(|| {
if let Some(syn::GenericParam::Type(type_param)) = generics.params.first() {
type_param.ident.clone()
} else {
panic!("Expected first type parameter");
}
});
let expanded = quote! {
impl #impl_generics gpui2::IntoAnyElement<#view_type> for #name #ty_generics #where_clause {
fn into_any(self) -> gpui2::AnyElement<#view_type> {
(move |view_state: &mut #view_type, cx: &mut gpui2::ViewContext<'_, '_, #view_type>| self.render(view_state, cx))
.into_any()
}
}
};
TokenStream::from(expanded)
}

View file

@ -1,6 +1,7 @@
use proc_macro::TokenStream;
mod derive_element;
mod derive_into_any_element;
mod style_helpers;
mod test;
@ -14,6 +15,11 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
derive_element::derive_element(input)
}
#[proc_macro_derive(IntoAnyElement, attributes(element))]
pub fn derive_into_any_element(input: TokenStream) -> TokenStream {
derive_into_any_element::derive_into_any_element(input)
}
#[proc_macro_attribute]
pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
test::test(args, function)

View file

@ -12,6 +12,7 @@ pub enum SplitDirection {
Vertical,
}
#[derive(IntoAnyElement)]
pub struct Pane<V: 'static> {
id: ElementId,
size: Size<Length>,
@ -19,12 +20,12 @@ pub struct Pane<V: 'static> {
children: SmallVec<[AnyElement<V>; 2]>,
}
impl<V: 'static> IntoAnyElement<V> for Pane<V> {
fn into_any(self) -> AnyElement<V> {
(move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx))
.into_any()
}
}
// impl<V: 'static> IntoAnyElement<V> for Pane<V> {
// fn into_any(self) -> AnyElement<V> {
// (move |view_state: &mut V, cx: &mut ViewContext<'_, '_, V>| self.render(view_state, cx))
// .into_any()
// }
// }
impl<V: 'static> Pane<V> {
pub fn new(id: impl Into<ElementId>, size: Size<Length>) -> Self {

View file

@ -28,14 +28,23 @@ impl Default for ToolGroup {
}
}
#[derive(Element)]
#[element(view_state = "Workspace")]
#[derive(IntoAnyElement)]
#[element(view_type = "Workspace")]
pub struct StatusBar {
left_tools: Option<ToolGroup>,
right_tools: Option<ToolGroup>,
bottom_tools: Option<ToolGroup>,
}
// impl IntoAnyElement<Workspace> for StatusBar {
// fn into_any(self) -> gpui2::AnyElement<Workspace> {
// (move |workspace: &mut Workspace, cx: &mut ViewContext<'_, '_, Workspace>| {
// self.render(workspace, cx)
// })
// .into_any()
// }
// }
impl StatusBar {
pub fn new() -> Self {
Self {
@ -83,7 +92,7 @@ impl StatusBar {
}
fn render(
&mut self,
self,
view: &mut Workspace,
cx: &mut ViewContext<Workspace>,
) -> impl IntoAnyElement<Workspace> {