From 334936b27609278e8887971eb11a23f2082bdd31 Mon Sep 17 00:00:00 2001 From: Ilya Maximov Date: Sat, 19 Mar 2022 21:04:48 +0100 Subject: [PATCH 1/4] fix: typos --- packages/core-macro/src/inlineprops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-macro/src/inlineprops.rs b/packages/core-macro/src/inlineprops.rs index ac71d5601..211f8be95 100644 --- a/packages/core-macro/src/inlineprops.rs +++ b/packages/core-macro/src/inlineprops.rs @@ -34,7 +34,7 @@ impl Parse for InlinePropsBody { let first_arg: FnArg = content.parse()?; let cx_token = { match first_arg { - FnArg::Receiver(_) => panic!("first argument must not be a reciver argument"), + FnArg::Receiver(_) => panic!("first argument must not be a receiver argument"), FnArg::Typed(f) => f.pat, } }; From 46b7f3b62308907f4acca705d3a76dba1633356a Mon Sep 17 00:00:00 2001 From: Ilya Maximov Date: Sun, 20 Mar 2022 20:59:30 +0100 Subject: [PATCH 2/4] feat: basic generic support --- packages/core-macro/src/inlineprops.rs | 49 +++++++++++++++++++++----- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/packages/core-macro/src/inlineprops.rs b/packages/core-macro/src/inlineprops.rs index 211f8be95..a0f12706a 100644 --- a/packages/core-macro/src/inlineprops.rs +++ b/packages/core-macro/src/inlineprops.rs @@ -3,7 +3,7 @@ use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ parse::{Parse, ParseStream}, punctuated::Punctuated, - token, Block, FnArg, Generics, Ident, Pat, Result, ReturnType, Token, Visibility, + *, }; pub struct InlinePropsBody { @@ -86,26 +86,57 @@ impl ToTokens for InlinePropsBody { FnArg::Typed(t) => Some(&t.pat), }); - let modifiers = if generics.params.is_empty() { - quote! { #[derive(Props, PartialEq)] } + let first_lifetime = if let Some(GenericParam::Lifetime(lt)) = generics.params.first() { + Some(lt) } else { - quote! { #[derive(Props)] } + None }; - let lifetime = if generics.params.is_empty() { - quote! {} + let modifiers = if first_lifetime.is_some() { + quote! { #[derive(Props)] } } else { - quote! { 'a, } + quote! { #[derive(Props, PartialEq)] } + }; + + let (scope_lifetime, fn_generics, struct_generics) = if let Some(lt) = first_lifetime { + let struct_generics: Punctuated<_, token::Comma> = generics + .params + .iter() + .map(|it| match it { + GenericParam::Type(tp) => { + let mut tp = tp.clone(); + tp.bounds.push(parse_quote!( 'a )); + + GenericParam::Type(tp) + } + _ => it.clone(), + }) + .collect(); + + ( + quote! { #lt, }, + generics.clone(), + quote! { <#struct_generics> }, + ) + } else { + let lifetime: LifetimeDef = parse_quote! { 'a }; + + let mut fn_generics = generics.clone(); + fn_generics + .params + .insert(0, GenericParam::Lifetime(lifetime.clone())); + + (quote! { #lifetime, }, fn_generics, quote! { #generics }) }; out_tokens.append_all(quote! { #modifiers #[allow(non_camel_case_types)] - #vis struct #struct_name #generics { + #vis struct #struct_name #struct_generics { #(#fields),* } - #vis fn #ident #generics (#cx_token: Scope<#lifetime #struct_name #generics>) #output { + #vis fn #ident #fn_generics (#cx_token: Scope<#scope_lifetime #struct_name #generics>) #output { let #struct_name { #(#field_names),* } = &cx.props; #block } From ff459f7297e7344fcb8eba6d769665eb3291cc10 Mon Sep 17 00:00:00 2001 From: Ilya Maximov Date: Sun, 20 Mar 2022 20:59:50 +0100 Subject: [PATCH 3/4] docs: an example for inlineprops --- examples/README.md | 17 +++++++++-------- examples/inlineprops.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 examples/inlineprops.rs diff --git a/examples/README.md b/examples/README.md index e108c56cd..1f96c66bb 100644 --- a/examples/README.md +++ b/examples/README.md @@ -41,6 +41,7 @@ These examples are not necessarily meant to be run, but rather serve as a refere | [Anti-patterns](./antipatterns.rs) | A collection of discouraged patterns | ✅ | | [Complete rsx reference](./rsx_usage.rs) | A complete reference for all rsx! usage | ✅ | | [Event Listeners](./listener.rs) | Attach closures to events on elements | ✅ | +| [Inline Props](./inlineprops.rs) | Using the `#[inling_props]` macro | ✅ | ## Show me some examples! @@ -51,7 +52,7 @@ In our collection of examples, guides, and tutorials, we have: - The reference (a collection of examples with heavy documentation) - The general examples - The platform-specific examples (web, ssr, desktop, mobile, server) - + Here's what a few common tasks look like in Dioxus: Nested components with children and internal state: @@ -80,7 +81,7 @@ Controlled inputs: ```rust fn App(cx: Scope) -> Element { let value = use_state(&cx, String::new); - cx.render(rsx!( + cx.render(rsx!( input { "type": "text", value: "{value}", @@ -96,16 +97,16 @@ fn App(cx: Scope) -> Element { let list = (0..10).map(|i| { rsx!(li { key: "{i}", "Value: {i}" }) }); - + let title = match list.len() { 0 => rsx!("Not enough"), _ => rsx!("Plenty!"), }; if should_show { - cx.render(rsx!( + cx.render(rsx!( title, - ul { list } + ul { list } )) } else { None @@ -165,18 +166,18 @@ fn App(cx: Scope) -> Element { Route::Home => rsx!( Home {} ), Route::Post(id) => rsx!( Post { id: id }) } - })) + })) } ``` -Suspense +Suspense ```rust fn App(cx: Scope) -> Element { let doggo = use_suspense(cx, || async { reqwest::get("https://dog.ceo/api/breeds/image/random").await.unwrap().json::().await.unwrap() }, |response| cx.render(rsx!( img { src: "{response.message}" })) ); - + cx.render(rsx!{ div { "One doggo coming right up:", diff --git a/examples/inlineprops.rs b/examples/inlineprops.rs new file mode 100644 index 000000000..e63d5977d --- /dev/null +++ b/examples/inlineprops.rs @@ -0,0 +1,41 @@ +//! Run with `cargo-expand` to see what each one expands to +#![allow(non_snake_case)] + +use dioxus::prelude::*; + +#[inline_props] +fn Thing1(cx: Scope, _a: T) -> Element { + cx.render(rsx! { "" }) +} + +#[inline_props] +fn Thing2(cx: Scope, _a: u32) -> Element<'a> { + cx.render(rsx! { "" }) +} + +#[inline_props] +fn Thing3<'a, T>(cx: Scope<'a>, _a: &'a T) -> Element<'a> { + cx.render(rsx! { "" }) +} + +#[inline_props] +fn Thing4<'a>(cx: Scope<'a>, _a: &'a u32) -> Element<'a> { + cx.render(rsx! { "" }) +} + +fn main() { + dioxus::desktop::launch(app); +} + +fn app(cx: Scope) -> Element { + let state = use_state(&cx, || 1); + + cx.render(rsx! { + div { + Thing1 { _a: 1 }, + Thing2 { _a: 1 }, + Thing3 { _a: state }, + Thing4 { _a: state }, + } + }) +} From a762c25b7e432043203a5c162148da24051b993d Mon Sep 17 00:00:00 2001 From: Ilya Maximov Date: Sun, 20 Mar 2022 21:04:48 +0100 Subject: [PATCH 4/4] docs: typo in readme --- examples/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/README.md b/examples/README.md index 1f96c66bb..69d15cf86 100644 --- a/examples/README.md +++ b/examples/README.md @@ -41,7 +41,7 @@ These examples are not necessarily meant to be run, but rather serve as a refere | [Anti-patterns](./antipatterns.rs) | A collection of discouraged patterns | ✅ | | [Complete rsx reference](./rsx_usage.rs) | A complete reference for all rsx! usage | ✅ | | [Event Listeners](./listener.rs) | Attach closures to events on elements | ✅ | -| [Inline Props](./inlineprops.rs) | Using the `#[inling_props]` macro | ✅ | +| [Inline Props](./inlineprops.rs) | Using the `#[inline_props]` macro | ✅ | ## Show me some examples!