From 4efc46c7632c7bf4bd2b17fca5785d0d8872a0a3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 15 Aug 2023 21:04:48 -0600 Subject: [PATCH] Add derive macro now new elements --- crates/gpui/playground/src/components.rs | 59 ++++---- crates/gpui/playground/src/playground.rs | 1 - .../playground_macros/src/derive_element.rs | 132 ++++++++++++------ .../src/playground_macros.rs | 5 + 4 files changed, 129 insertions(+), 68 deletions(-) diff --git a/crates/gpui/playground/src/components.rs b/crates/gpui/playground/src/components.rs index 055a9d63e6..d92583866d 100644 --- a/crates/gpui/playground/src/components.rs +++ b/crates/gpui/playground/src/components.rs @@ -1,9 +1,10 @@ use crate::{ - element::{AnyElement, Element, ElementMetadata}, + element::{Element, ElementMetadata}, frame, themes::rose_pine, }; use gpui::ViewContext; +use playground_macros::Element; use std::{borrow::Cow, marker::PhantomData, rc::Rc}; struct ButtonHandlers { @@ -16,6 +17,8 @@ impl Default for ButtonHandlers { } } +#[derive(Element)] +#[element_crate = "crate"] pub struct Button { metadata: ElementMetadata, handlers: ButtonHandlers, @@ -89,34 +92,34 @@ impl Button { } } -impl Element for Button { - type Layout = AnyElement; +// impl Element for Button { +// type Layout = AnyElement; - fn style_mut(&mut self) -> &mut crate::style::ElementStyle { - &mut self.metadata.style - } +// fn style_mut(&mut self) -> &mut crate::style::ElementStyle { +// &mut self.metadata.style +// } - fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers { - &mut self.metadata.handlers - } +// fn handlers_mut(&mut self) -> &mut crate::element::ElementHandlers { +// &mut self.metadata.handlers +// } - fn layout( - &mut self, - view: &mut V, - cx: &mut crate::element::LayoutContext, - ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> { - let mut element = self.render(view, cx).into_any(); - let node_id = element.layout(view, cx)?; - Ok((node_id, element)) - } +// fn layout( +// &mut self, +// view: &mut V, +// cx: &mut crate::element::LayoutContext, +// ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> { +// let mut element = self.render(view, cx).into_any(); +// let node_id = element.layout(view, cx)?; +// Ok((node_id, element)) +// } - fn paint<'a>( - &mut self, - layout: crate::element::Layout<'a, Self::Layout>, - view: &mut V, - cx: &mut crate::element::PaintContext, - ) -> anyhow::Result<()> { - layout.from_element.paint(view, cx)?; - Ok(()) - } -} +// fn paint<'a>( +// &mut self, +// layout: crate::element::Layout<'a, Self::Layout>, +// view: &mut V, +// cx: &mut crate::element::PaintContext, +// ) -> anyhow::Result<()> { +// layout.from_element.paint(view, cx)?; +// Ok(()) +// } +// } diff --git a/crates/gpui/playground/src/playground.rs b/crates/gpui/playground/src/playground.rs index feed975eff..3d668857d2 100644 --- a/crates/gpui/playground/src/playground.rs +++ b/crates/gpui/playground/src/playground.rs @@ -42,7 +42,6 @@ fn main() { } fn workspace(theme: &ThemeColors) -> impl Element { - // frame().w_full().h_half().fill(theme.success(0.5)) frame() .h_full() .w(percent(50.)) diff --git a/crates/gpui/playground_macros/src/derive_element.rs b/crates/gpui/playground_macros/src/derive_element.rs index 8ea63cf620..546267f1bf 100644 --- a/crates/gpui/playground_macros/src/derive_element.rs +++ b/crates/gpui/playground_macros/src/derive_element.rs @@ -1,48 +1,102 @@ -// type Result = (); -// type LayoutContext<> = (); +use proc_macro::TokenStream; +use quote::{format_ident, quote}; +use syn::{ + parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics, Ident, Lit, Meta, + WhereClause, +}; -// trait Element: 'static + Clone { -// type Layout: 'static; +pub fn derive_element(input: TokenStream) -> TokenStream { + let ast = parse_macro_input!(input as DeriveInput); + let type_name = ast.ident; -// fn style_mut(&mut self) -> &mut Style; -// fn layout(&mut self, view: &mut V, cx: &mut LayoutContext) -// -> Result<(NodeId, Self::Layout)>; -// fn paint<'a>( -// &mut self, -// layout: Layout<'a, Self::Layout>, -// view: &mut V, -// cx: &mut PaintContext, -// ) -> Result<()>; -// } + let crate_name: String = ast + .attrs + .iter() + .find_map(|attr| { + if attr.path.is_ident("element_crate") { + match attr.parse_meta() { + Ok(Meta::NameValue(nv)) => { + if let Lit::Str(s) = nv.lit { + Some(s.value()) + } else { + None + } + } + _ => None, + } + } else { + None + } + }) + .unwrap_or_else(|| String::from("playground")); -// struct Button { -// style: Style, -// } + let crate_name = format_ident!("{}", crate_name); -// type Style = (); + let placeholder_view_generics: Generics = parse_quote! { }; + let placeholder_view_type_name: Ident = parse_quote! { V }; + let view_type_name: Ident; + let impl_generics: syn::ImplGenerics<'_>; + let type_generics: Option>; + let where_clause: Option<&'_ WhereClause>; -// impl Button { -// fn render() -> impl Element { -// todo!() -// } -// } + match ast.generics.params.iter().find_map(|param| { + if let GenericParam::Type(type_param) = param { + Some(type_param.ident.clone()) + } else { + None + } + }) { + Some(type_name) => { + view_type_name = type_name; + let generics = ast.generics.split_for_impl(); + impl_generics = generics.0; + type_generics = Some(generics.1); + where_clause = generics.2; + } + _ => { + view_type_name = placeholder_view_type_name; + let generics = placeholder_view_generics.split_for_impl(); + impl_generics = generics.0; + type_generics = None; + where_clause = generics.2; + } + } -// impl Element for Foo { -// type Layout = (); + let gen = quote! { + impl #impl_generics #crate_name::element::Element<#view_type_name> for #type_name #type_generics + #where_clause + { + type Layout = #crate_name::element::AnyElement; -// fn style_mut(&mut self) -> &mut Style { -// unimplemented!() -// } + fn style_mut(&mut self) -> &mut #crate_name::style::ElementStyle { + &mut self.metadata.style + } -// fn layout( -// &mut self, -// view: &mut V, -// cx: &mut LayoutContext, -// ) -> Result<(NodeId, Self::Layout)> { -// unimplemented!() -// } + fn handlers_mut(&mut self) -> &mut #crate_name::element::ElementHandlers { + &mut self.metadata.handlers + } -// fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext) -> Result<()> { -// unimplemented!() -// } -// } + fn layout( + &mut self, + view: &mut V, + cx: &mut #crate_name::element::LayoutContext, + ) -> anyhow::Result<(taffy::tree::NodeId, Self::Layout)> { + let mut element = self.render(view, cx).into_any(); + let node_id = element.layout(view, cx)?; + Ok((node_id, element)) + } + + fn paint<'a>( + &mut self, + layout: #crate_name::element::Layout<'a, Self::Layout>, + view: &mut V, + cx: &mut #crate_name::element::PaintContext, + ) -> anyhow::Result<()> { + layout.from_element.paint(view, cx)?; + Ok(()) + } + } + }; + + gen.into() +} diff --git a/crates/gpui/playground_macros/src/playground_macros.rs b/crates/gpui/playground_macros/src/playground_macros.rs index 1ea6ea9894..446b476981 100644 --- a/crates/gpui/playground_macros/src/playground_macros.rs +++ b/crates/gpui/playground_macros/src/playground_macros.rs @@ -7,3 +7,8 @@ mod tailwind_lengths; pub fn tailwind_lengths(attr: TokenStream, item: TokenStream) -> TokenStream { tailwind_lengths::tailwind_lengths(attr, item) } + +#[proc_macro_derive(Element, attributes(element_crate))] +pub fn derive_element(input: TokenStream) -> TokenStream { + derive_element::derive_element(input) +}