Merge branch 'gpui2-element-renderer' into zed2
This commit is contained in:
commit
d62c51a4b8
66 changed files with 897 additions and 1346 deletions
66
crates/gpui2_macros/src/derive_component.rs
Normal file
66
crates/gpui2_macros/src/derive_component.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, parse_quote, DeriveInput};
|
||||
|
||||
pub fn derive_component(input: TokenStream) -> TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
let 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 (_, ty_generics, _) = ast.generics.split_for_impl();
|
||||
|
||||
let expanded = quote! {
|
||||
impl #impl_generics gpui2::Component<#view_type> for #name #ty_generics #where_clause {
|
||||
fn render(self) -> gpui2::AnyElement<#view_type> {
|
||||
(move |view_state: &mut #view_type, cx: &mut gpui2::ViewContext<'_, '_, #view_type>| self.render(view_state, cx))
|
||||
.render()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
fn specified_view_type(ast: &DeriveInput) -> Option<proc_macro2::Ident> {
|
||||
let component_attr = ast
|
||||
.attrs
|
||||
.iter()
|
||||
.find(|attr| attr.path.is_ident("component"))?;
|
||||
|
||||
if let Ok(syn::Meta::List(meta_list)) = component_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
|
||||
}
|
||||
}
|
|
@ -1,95 +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 state_type = quote! { () };
|
||||
|
||||
for param in &ast.generics.params {
|
||||
if let GenericParam::Type(type_param) = param {
|
||||
let type_ident = &type_param.ident;
|
||||
state_type = 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 {
|
||||
state_type = lit_str.value().parse().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
let gen = quote! {
|
||||
impl #impl_generics gpui2::IntoAnyElement<#state_type> for #type_name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
fn into_any(self) -> gpui2::AnyElement<#state_type> {
|
||||
gpui2::AnyElement::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics gpui2::Element for #type_name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
type ViewState = #state_type;
|
||||
type ElementState = gpui2::AnyElement<#state_type>;
|
||||
|
||||
fn id(&self) -> Option<gpui2::ElementId> {
|
||||
None
|
||||
}
|
||||
|
||||
fn initialize(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
_: Option<Self::ElementState>,
|
||||
cx: &mut gpui2::ViewContext<Self::ViewState>
|
||||
) -> Self::ElementState {
|
||||
use gpui2::IntoAnyElement;
|
||||
|
||||
let mut element = self.render(view_state, cx).into_any();
|
||||
element.initialize(view_state, cx);
|
||||
element
|
||||
}
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view_state: &mut Self::ViewState,
|
||||
rendered_element: &mut Self::ElementState,
|
||||
cx: &mut gpui2::ViewContext<Self::ViewState>,
|
||||
) -> gpui2::LayoutId {
|
||||
rendered_element.layout(view_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: gpui2::Bounds<gpui2::Pixels>,
|
||||
view_state: &mut Self::ViewState,
|
||||
rendered_element: &mut Self::ElementState,
|
||||
cx: &mut gpui2::ViewContext<Self::ViewState>,
|
||||
) {
|
||||
rendered_element.paint(view_state, cx)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gen.into()
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
use proc_macro::TokenStream;
|
||||
|
||||
mod derive_element;
|
||||
mod derive_component;
|
||||
mod style_helpers;
|
||||
mod test;
|
||||
|
||||
|
@ -9,9 +9,9 @@ pub fn style_helpers(args: TokenStream) -> TokenStream {
|
|||
style_helpers::style_helpers(args)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Element, attributes(element))]
|
||||
pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||
derive_element::derive_element(input)
|
||||
#[proc_macro_derive(Component, attributes(component))]
|
||||
pub fn derive_component(input: TokenStream) -> TokenStream {
|
||||
derive_component::derive_component(input)
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue