Skip to content

Commit

Permalink
Allow adding derives to generated prop type for inline_props (#750)
Browse files Browse the repository at this point in the history
* feat(macro): inline_props additional struct attributes

* fix(macro): remove redundunt into_iter

* fix(macro): inline_props struct attributes fixes

* feat(macro): support other style of attributes for inline_props
  • Loading branch information
davidon-top authored Nov 3, 2024
1 parent cb4f9ec commit ed3cabc
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
40 changes: 32 additions & 8 deletions packages/sycamore-macro/src/component.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! The `#[component]` attribute macro implementation.
use proc_macro2::TokenStream;
use proc_macro2::{Span, TokenStream};
use quote::{format_ident, quote, ToTokens};
use syn::parse::{Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{
parse_quote, Error, Expr, FnArg, Generics, Ident, Item, ItemFn, Pat, PatIdent, Result,
ReturnType, Signature, Token, Type, TypeTuple,
parse_quote, AttrStyle, Attribute, Error, Expr, FnArg, Generics, Ident, Item, ItemFn, Meta,
Pat, PatIdent, Result, ReturnType, Signature, Token, Type, TypeTuple,
};

pub struct ComponentFn {
pub f: ItemFn,
}
Expand Down Expand Up @@ -222,25 +223,41 @@ impl ToTokens for ComponentFn {
/// Arguments to the `component` attribute proc-macro.
pub struct ComponentArgs {
inline_props: Option<Ident>,
_comma: Option<Token![,]>,
attrs: Punctuated<Meta, Token![,]>,
}

impl Parse for ComponentArgs {
fn parse(input: ParseStream) -> Result<Self> {
let inline_props: Option<Ident> = input.parse()?;
if let Some(inline_props) = &inline_props {
let (comma, attrs) = if let Some(inline_props) = &inline_props {
// Check if the ident is correct.
if *inline_props != "inline_props" {
return Err(Error::new(inline_props.span(), "expected `inline_props`"));
}
}
Ok(Self { inline_props })

let comma: Option<Token![,]> = input.parse()?;
let attrs: Punctuated<Meta, Token![,]> = if comma.is_some() {
input.parse_terminated(Meta::parse, Token![,])?
} else {
Punctuated::new()
};
(comma, attrs)
} else {
(None, Punctuated::new())
};
Ok(Self {
inline_props,
_comma: comma,
attrs,
})
}
}

pub fn component_impl(args: ComponentArgs, item: TokenStream) -> Result<TokenStream> {
if args.inline_props.is_some() {
let mut item_fn = syn::parse::<ItemFn>(item.into())?;
let inline_props = inline_props_impl(&mut item_fn)?;
let inline_props = inline_props_impl(&mut item_fn, args.attrs)?;
// TODO: don't parse the function twice.
let comp = syn::parse::<ComponentFn>(item_fn.to_token_stream().into())?;
Ok(quote! {
Expand All @@ -255,7 +272,7 @@ pub fn component_impl(args: ComponentArgs, item: TokenStream) -> Result<TokenStr

/// Codegens the new props struct and modifies the component body to accept this new struct as
/// props.
fn inline_props_impl(item: &mut ItemFn) -> Result<TokenStream> {
fn inline_props_impl(item: &mut ItemFn, attrs: Punctuated<Meta, Token![,]>) -> Result<TokenStream> {
let props_vis = &item.vis;
let props_struct_ident = format_ident!("{}_Props", item.sig.ident);

Expand Down Expand Up @@ -307,10 +324,17 @@ fn inline_props_impl(item: &mut ItemFn) -> Result<TokenStream> {

let doc_comment = format!("Props for [`{}`].", item.sig.ident);

let attrs = attrs.into_iter().map(|a| Attribute {
pound_token: Token![#](Span::call_site()),
style: AttrStyle::Outer,
bracket_token: Default::default(),
meta: a,
});
let ret = Ok(quote! {
#[allow(non_camel_case_types)]
#[doc = #doc_comment]
#[derive(::sycamore::rt::Props)]
#(#attrs)*
#props_vis struct #props_struct_ident #generics {
#(#fields,)*
#(#generics_phantoms,)*
Expand Down
11 changes: 10 additions & 1 deletion packages/sycamore-macro/tests/component/inline-props-pass.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use sycamore::prelude::{component, view, Signal, View};
use sycamore::prelude::{component, view, Signal, View, Props};

#[component(inline_props)]
fn NoProps() -> View {
Expand Down Expand Up @@ -75,4 +75,13 @@ fn PropsWithVariousImplGenerics(
}
}

#[component(inline_props, derive(Clone), derive(Debug))]
fn AdditionalStructAttributes(dummy: String) -> View {
let props = AdditionalStructAttributes_Props::builder().dummy(dummy).build();

view! {
(format!("{:?}", props.clone()))
}
}

fn main() {}

0 comments on commit ed3cabc

Please sign in to comment.