From 859672a9983340498890e480feaf3078174aa62e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:06:30 +0100 Subject: [PATCH 01/21] Merge port of yew-autopros in Yew to yew-autoprops --- .github/workflows/rust.yml | 18 +- Cargo.toml | 5 +- src/autoprops.rs | 258 ++++++++++++++++++ src/function_component.rs | 24 ++ src/lib.rs | 175 +----------- tests/cases/allow-refs-pass.rs | 15 - tests/cases/attrs-pass.rs | 43 --- tests/cases/generics-pass.rs | 20 -- tests/cases/hooks-pass.rs | 20 -- tests/cases/name-pass.rs | 17 -- tests/cases/partialeq-fail.rs | 29 -- tests/cases/partialeq-fail.stderr | 17 -- tests/cases/partialeq-pass.rs | 31 --- tests/function_attr_test.rs | 7 + .../function_component_attr/autoprops-fail.rs | 67 +++++ .../autoprops-fail.stderr | 59 ++++ .../function_component_attr/autoprops-pass.rs | 112 ++++++++ tests/test.rs | 6 - 18 files changed, 551 insertions(+), 372 deletions(-) create mode 100644 src/autoprops.rs create mode 100644 src/function_component.rs delete mode 100644 tests/cases/allow-refs-pass.rs delete mode 100644 tests/cases/attrs-pass.rs delete mode 100644 tests/cases/generics-pass.rs delete mode 100644 tests/cases/hooks-pass.rs delete mode 100644 tests/cases/name-pass.rs delete mode 100644 tests/cases/partialeq-fail.rs delete mode 100644 tests/cases/partialeq-fail.stderr delete mode 100644 tests/cases/partialeq-pass.rs create mode 100644 tests/function_attr_test.rs create mode 100644 tests/function_component_attr/autoprops-fail.rs create mode 100644 tests/function_component_attr/autoprops-fail.stderr create mode 100644 tests/function_component_attr/autoprops-pass.rs delete mode 100644 tests/test.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d54fa2f..c33adf7 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -2,21 +2,23 @@ name: Rust on: push: - branches: [ "master" ] + branches: [ "main" ] pull_request: - branches: [ "master" ] + branches: [ "main" ] env: CARGO_TERM_COLOR: always jobs: build: - + strategy: + matrix: + rust: + - stable + - 1.64.0 runs-on: ubuntu-latest - steps: - uses: actions/checkout@v3 - - name: Build - run: cargo build --verbose - - name: Run tests - run: cargo test --verbose + - run: rustup default ${{ matrix.rust }} + - run: cargo build --verbose + - run: cargo test --verbose diff --git a/Cargo.toml b/Cargo.toml index 774d4ea..7a1d4e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,5 +23,6 @@ [dev-dependencies] - yew = { version = "0.21" } - trybuild = "1" + yew = { version = "0.21" } + trybuild = "1" + rustversion = "1" diff --git a/src/autoprops.rs b/src/autoprops.rs new file mode 100644 index 0000000..b0b3e69 --- /dev/null +++ b/src/autoprops.rs @@ -0,0 +1,258 @@ +use crate::function_component::FunctionComponentName; +use quote::{quote, quote_spanned}; +use syn::spanned::Spanned; + +#[derive(Clone)] +pub struct Autoprops { + item_fn: syn::ItemFn, + properties_name: syn::Ident, +} + +impl syn::parse::Parse for Autoprops { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let parsed: syn::Item = input.parse()?; + + let item_fn = match parsed { + syn::Item::Fn(m) => m, + item => { + return Err(syn::Error::new_spanned( + item, + "`autoprops` attribute can only be applied to functions", + )) + } + }; + + let syn::ItemFn { attrs, sig, .. } = &item_fn; + + let mut component_name = item_fn.sig.ident.clone(); + + attrs + .iter() + .find(|attr| { + match &attr.meta { + syn::Meta::Path(path) => { + if let Some(last_segment) = path.segments.last() { + if last_segment.ident == "function_component" { + return true; + } + } + } + syn::Meta::List(syn::MetaList { path, tokens, .. }) => { + if let Some(last_segment) = path.segments.last() { + if last_segment.ident == "function_component" { + if let Ok(attr) = + syn::parse2::(tokens.clone()) + { + if let Some(name) = attr.component_name { + component_name = name; + } + } + return true; + } + } + } + _ => {} + } + false + }) + .ok_or_else(|| { + syn::Error::new_spanned( + sig, + "could not find #[function_component] attribute in function declaration \ + (#[autoprops] must be placed *before* #[function_component])", + ) + })?; + + for input in &sig.inputs { + if let syn::FnArg::Typed(syn::PatType { pat, .. }) = input { + if let syn::Pat::Wild(wild) = pat.as_ref() { + return Err(syn::Error::new_spanned( + wild, + "cannot use `_` as field name", + )); + } + } + } + + let properties_name = syn::Ident::new( + &format!("{}Props", component_name), + proc_macro2::Span::call_site(), + ); + + Ok(Self { + properties_name, + item_fn, + }) + } +} + +impl Autoprops { + pub fn apply_args(&mut self, args: AutopropsArgs) { + if let Some(name) = args.properties_name { + self.properties_name = name; + } + } + + fn print_function_component(&self) -> proc_macro2::TokenStream { + let properties_name = &self.properties_name; + let syn::ItemFn { + attrs, + vis, + sig, + block, + } = &self.item_fn; + + let fn_name = &sig.ident; + let (impl_generics, type_generics, where_clause) = sig.generics.split_for_impl(); + let inputs = if self.needs_a_properties_struct() { + // NOTE: function components currently don't accept receivers, we're just passing the + // information to the next macro to fail and give its own error message + let receivers = sig + .inputs + .iter() + .filter_map(|arg| match arg { + syn::FnArg::Receiver(receiver) => Some(receiver), + _ => None, + }) + .collect::>(); + let args = sig + .inputs + .iter() + .filter_map(|arg| match arg { + syn::FnArg::Typed(syn::PatType { pat, .. }) => Some(quote! { #pat }), + _ => None, + }) + .collect::>(); + let phantom = sig.generics.type_params().next().is_some().then(|| { + quote! { + , phantom: _ + } + }); + quote! { + #(#receivers,)* #properties_name { + #(#args),* + #phantom + }: &#properties_name #type_generics + } + } else { + quote! {} + }; + let clones = sig + .inputs + .iter() + .filter_map(|arg| match arg { + syn::FnArg::Typed(syn::PatType { pat, ty, .. }) + if !matches!(**ty, syn::Type::Reference(_)) => + { + Some(quote! { let #pat = ::std::clone::Clone::clone(#pat); }) + } + _ => None, + }) + .collect::>(); + + quote! { + #(#attrs)* + #vis fn #fn_name #impl_generics (#inputs) -> ::yew::Html #where_clause { + #(#clones)* + #block + } + } + } + + fn print_properties_struct(&self) -> proc_macro2::TokenStream { + let properties_name = &self.properties_name; + let syn::ItemFn { vis, sig, .. } = &self.item_fn; + + if !self.needs_a_properties_struct() { + return quote! {}; + } + + let (impl_generics, type_generics, where_clause) = sig.generics.split_for_impl(); + let fields = sig + .inputs + .iter() + .filter_map(|arg| match arg { + syn::FnArg::Typed(syn::PatType { attrs, pat, ty, .. }) => match ty.as_ref() { + syn::Type::Reference(syn::TypeReference { elem, .. }) => { + Some(quote! { #(#attrs)* #pat: #elem, }) + } + _ => Some(quote! { #(#attrs)* #pat: #ty, }), + }, + _ => None, + }) + .collect::>(); + let type_params = sig + .generics + .type_params() + .map(|param| ¶m.ident) + .collect::>(); + let phantom = (!type_params.is_empty()).then(|| { + quote! { + #[prop_or_default] + phantom: ::std::marker::PhantomData <( #(#type_params),* )>, + } + }); + let fields_eq = sig + .inputs + .iter() + .filter_map(|arg| match arg { + syn::FnArg::Typed(syn::PatType { pat, ty, .. }) => Some(quote_spanned! { + ty.span() => self.#pat == rhs.#pat && + }), + _ => None, + }) + .collect::>(); + + quote! { + #[derive(::yew::Properties)] + #vis struct #properties_name #impl_generics #where_clause { + #(#fields)* + #phantom + } + + impl #impl_generics ::std::cmp::PartialEq for #properties_name #type_generics + #where_clause { + fn eq(&self, rhs: &Self) -> ::std::primitive::bool { + #(#fields_eq)* true + } + } + } + } + + fn needs_a_properties_struct(&self) -> bool { + let syn::ItemFn { sig, .. } = &self.item_fn; + !sig.inputs.is_empty() || sig.generics.type_params().next().is_some() + } +} + +impl quote::ToTokens for Autoprops { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + let function_component = self.print_function_component(); + let properties_struct = self.print_properties_struct(); + + tokens.extend(quote! { + #function_component + #properties_struct + }) + } +} + +pub struct AutopropsArgs { + pub properties_name: Option, +} + +impl syn::parse::Parse for AutopropsArgs { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + if input.is_empty() { + return Ok(Self { + properties_name: None, + }); + } + + let properties_name = input.parse()?; + + Ok(Self { + properties_name: Some(properties_name), + }) + } +} diff --git a/src/function_component.rs b/src/function_component.rs new file mode 100644 index 0000000..eae5172 --- /dev/null +++ b/src/function_component.rs @@ -0,0 +1,24 @@ +// copy-pasted from yew-macro because proc-macro crates cannot export any items + +use syn::parse::{Parse, ParseStream}; +use syn::Ident; + +pub struct FunctionComponentName { + pub component_name: Option, +} + +impl Parse for FunctionComponentName { + fn parse(input: ParseStream) -> syn::Result { + if input.is_empty() { + return Ok(Self { + component_name: None, + }); + } + + let component_name = input.parse()?; + + Ok(Self { + component_name: Some(component_name), + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 0467478..58f086e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,170 +1,17 @@ -//! proc-macro to automatically derive Properties structs from args for Yew components -//! -//! No more extra one-off Props structs! -//! -//! -//! # Examples -//! -//! ``` -//! use yew_autoprops::autoprops_component; -//! use yew::prelude::*; -//! -//! #[autoprops_component] -//! fn CoolComponent(#[prop_or_default] hidden: bool, smth: &AttrValue) -> Html { -//! html! { -//!
-//!

{ smth }

-//!
-//! } -//! } -//! ``` -//! -//! ``` -//! use yew_autoprops::autoprops_component; -//! use yew::prelude::*; -//! -//! #[autoprops_component(CoolComponent)] -//! fn cool_component(#[prop_or_default] hidden: bool, smth: &AttrValue) -> Html { -//! html! { -//!
-//!

{ smth }

-//!
-//! } -//! } -//! ``` -//! -extern crate proc_macro; +mod autoprops; +mod function_component; -use core::panic; - -use proc_macro2::{Span, TokenStream, TokenTree}; -use quote::{quote, ToTokens}; -use syn::{parse_macro_input, FnArg, ItemFn, Pat, PatType, Type}; +use quote::ToTokens; +//#[proc_macro_error::proc_macro_error] #[proc_macro_attribute] -pub fn autoprops_component( - args: proc_macro::TokenStream, - input: proc_macro::TokenStream, +pub fn autoprops( + attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - let args = TokenStream::from(args).into_iter().collect::>(); - - let function = parse_macro_input!(input as ItemFn); - - let fn_name = &function.sig.ident; - let visibility = &function.vis; - let generics = &function.sig.generics; - - let (component_name, struct_name) = match args.len() { - 0 => ( - None, - Some(syn::Ident::new( - &format!("{}Props", fn_name), - Span::call_site().into(), - )), - ), - 1 => { - let TokenTree::Ident(name) = &args[0] else { - panic!("Invalid argument: {}", args[0].to_string()); - }; - - ( - Some(name), - Some(syn::Ident::new( - &format!("{}Props", name), - Span::call_site().into(), - )), - ) - } - 3 => { - let TokenTree::Ident(name) = &args[0] else { - panic!("Invalid argument: {}", args[0].to_string()); - }; - - let TokenTree::Ident(props) = args[2].clone() else { - panic!("Invalid argument: {}", args[2].to_string()); - }; - - (Some(name), Some(props)) - } - _ => panic!("Invalid arguments: {:?}", args), - }; - - let arg_names = function - .sig - .inputs - .iter() - .map(|input| { - if let FnArg::Typed(PatType { pat, .. }) = input { - if let Pat::Ident(ident) = pat.as_ref() { - return &ident.ident; - } - } - panic!("Invalid argument: {}", input.to_token_stream()); - }) - .collect::>(); - - let mut fields = Vec::new(); - let mut arg_types = Vec::new(); - let mut clones = Vec::new(); - let mut partial_eq_constraints = Vec::new(); - for input in function.sig.inputs.iter() { - if let FnArg::Typed(PatType { pat, ty, attrs, .. }) = input { - let mut end_ty = ty; - - if let Type::Reference(ty_ref) = ty.as_ref() { - end_ty = &ty_ref.elem; - } else { - clones.push(quote! { - let #pat = #pat.clone(); - }); - } - - fields.push(quote! { - #(#attrs)* - pub #pat: #end_ty - }); - arg_types.push(ty.clone()); - partial_eq_constraints.push(quote! { #end_ty: PartialEq, }); - } else { - panic!("Invalid argument"); - } - } - - let (impl_generics, ty_generics, _) = generics.split_for_impl(); - let bounds = generics.where_clause.clone(); - - let where_clause = if generics.params.is_empty() { - quote! {} - } else { - quote! { - where - #(#partial_eq_constraints)* - #bounds - } - }; - - let destructure = quote! { - #struct_name { #(#arg_names),* } - }; - - let function_block = function.block; - - let tokens = quote! { - #[derive(::yew::Properties, PartialEq)] - #visibility struct #struct_name #impl_generics #where_clause { - #(#fields),* - } - - #[::yew::function_component(#component_name)] - #[allow(non_snake_case)] - #visibility fn #fn_name #impl_generics (#destructure: &#struct_name #ty_generics) -> ::yew::Html #where_clause { - #(#clones)* - #function_block - } - }; - - // panic!("\n{}", tokens.to_string()); + let mut autoprops = syn::parse_macro_input!(item as autoprops::Autoprops); + let args = syn::parse_macro_input!(attr as autoprops::AutopropsArgs); + autoprops.apply_args(args); - // Return the new tokens - tokens.into() + proc_macro::TokenStream::from(autoprops.into_token_stream()) } diff --git a/tests/cases/allow-refs-pass.rs b/tests/cases/allow-refs-pass.rs deleted file mode 100644 index 6de445c..0000000 --- a/tests/cases/allow-refs-pass.rs +++ /dev/null @@ -1,15 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -#[autoprops_component] -fn CoolComponent(test: i8, smth: &usize) -> Html { - println!("test: {}", test); - - html! { -
-

{ smth }

-
- } -} - -fn main() {} diff --git a/tests/cases/attrs-pass.rs b/tests/cases/attrs-pass.rs deleted file mode 100644 index 9396f0a..0000000 --- a/tests/cases/attrs-pass.rs +++ /dev/null @@ -1,43 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -#[autoprops_component] -fn CoolComponent(#[prop_or_default] test: &i8, smth: &usize) -> Html { - println!("test: {}", test); - - html! { -
-

{ smth }

-
- } -} - -#[autoprops_component] -fn CoolComponent2(me: &i8, #[prop_or_default] pls: &usize) -> Html { - println!("pls: {}", pls); - - html! { -
-

{ me }

-
- } -} - -#[autoprops_component] -fn CoolComponent3(me: &i8, #[prop_or(2)] pls: &usize) -> Html { - println!("pls: {}", pls); - - html! { -
-

{ me }

-
- } -} - -fn main() { - fn main() { - let _ = html! { }; - let _ = html! { }; - let _ = html! { }; - } -} diff --git a/tests/cases/generics-pass.rs b/tests/cases/generics-pass.rs deleted file mode 100644 index 727a320..0000000 --- a/tests/cases/generics-pass.rs +++ /dev/null @@ -1,20 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -#[autoprops_component] -fn GenericComponent(value: &T) -> Html { - html! { -
- { value.to_string() } -
- } -} - -fn main() { - html! { - <> - value=1 /> - value="hi" /> - - }; -} diff --git a/tests/cases/hooks-pass.rs b/tests/cases/hooks-pass.rs deleted file mode 100644 index a49287f..0000000 --- a/tests/cases/hooks-pass.rs +++ /dev/null @@ -1,20 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -#[autoprops_component(CoolComponent)] -fn cool_component(#[prop_or_default] test: &i8, smth: &usize) -> Html { - println!("test: {}", test); - - let test_hook = use_state(|| 0); - - html! { -
-

{ smth }

-

{ *test_hook }

-
- } -} - -fn main() { - let _ = html! { }; -} diff --git a/tests/cases/name-pass.rs b/tests/cases/name-pass.rs deleted file mode 100644 index e54870b..0000000 --- a/tests/cases/name-pass.rs +++ /dev/null @@ -1,17 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -#[autoprops_component(CoolComponent)] -fn cool_component(#[prop_or_default] test: &i8, smth: &usize) -> Html { - println!("test: {}", test); - - html! { -
-

{ smth }

-
- } -} - -fn main() { - let _ = html! { }; -} diff --git a/tests/cases/partialeq-fail.rs b/tests/cases/partialeq-fail.rs deleted file mode 100644 index d00603b..0000000 --- a/tests/cases/partialeq-fail.rs +++ /dev/null @@ -1,29 +0,0 @@ -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -struct TestPEqStruct { - t: T, -} - -impl PartialEq for TestPEqStruct { - fn eq(&self, other: &Self) -> bool { - self.t == other.t - } -} - -struct NotPartialEq(); - -#[autoprops_component] -fn TestComponent(test_struct: &TestPEqStruct) -> Html { - html! { -
- { "TestComponent" } -
- } -} - -fn main() { - html! { - - }; -} diff --git a/tests/cases/partialeq-fail.stderr b/tests/cases/partialeq-fail.stderr deleted file mode 100644 index f35afa2..0000000 --- a/tests/cases/partialeq-fail.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0369]: binary operation `==` cannot be applied to type `TestPEqStruct` - --> tests/cases/partialeq-fail.rs:16:1 - | -16 | #[autoprops_component] - | ^^^^^^^^^^^^^^^^^^^^^^ - | -note: an implementation of `PartialEq` might be missing for `NotPartialEq` - --> tests/cases/partialeq-fail.rs:14:1 - | -14 | struct NotPartialEq(); - | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq` - = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) -help: consider annotating `NotPartialEq` with `#[derive(PartialEq)]` - | -14 + #[derive(PartialEq)] -15 | struct NotPartialEq(); - | diff --git a/tests/cases/partialeq-pass.rs b/tests/cases/partialeq-pass.rs deleted file mode 100644 index a873158..0000000 --- a/tests/cases/partialeq-pass.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::marker::PhantomData; -use yew::prelude::*; -use yew_autoprops::autoprops_component; - -struct TestPEqStruct { - _phantom: PhantomData, -} - -impl PartialEq for TestPEqStruct { - fn eq(&self, _other: &Self) -> bool { - true - } -} - -struct NotPartialEq(); - -#[autoprops_component] -fn TestComponent(test_struct: &TestPEqStruct) -> Html { - assert!(test_struct == test_struct); - html! { -
- { "TestComponent" } -
- } -} - -fn main() { - html! { - - }; -} diff --git a/tests/function_attr_test.rs b/tests/function_attr_test.rs new file mode 100644 index 0000000..ed3cf9d --- /dev/null +++ b/tests/function_attr_test.rs @@ -0,0 +1,7 @@ +#[allow(dead_code)] +#[rustversion::attr(stable(1.64), test)] +fn tests() { + let t = trybuild::TestCases::new(); + t.pass("tests/function_component_attr/*-pass.rs"); + t.compile_fail("tests/function_component_attr/*-fail.rs"); +} diff --git a/tests/function_component_attr/autoprops-fail.rs b/tests/function_component_attr/autoprops-fail.rs new file mode 100644 index 0000000..36f1f70 --- /dev/null +++ b/tests/function_component_attr/autoprops-fail.rs @@ -0,0 +1,67 @@ +use yew::prelude::*; +use yew_autoprops::*; + +#[autoprops] +#[function_component] +fn CantAcceptReceiver(&self, b: bool) -> Html { + html! { +

{b}

+ } +} + +#[autoprops] +fn not_a_function_component(b: bool) -> Html { + html! { +

{b}

+ } +} + +#[function_component(WrongAttrsOrder)] +#[autoprops] +fn wrong_attrs_order(b: bool) -> Html { + html! { +

{b}

+ } +} + +#[autoprops] +#[function_component(let)] +fn BadFunctionComponent(b: bool) -> Html { + html! { +

{b}

+ } +} + +#[derive(PartialEq)] +struct NotClonable(u32); + +#[autoprops] +#[function_component] +fn TypeIsNotClone(stuff: NotClonable) -> Html { + drop(stuff); + html! { +

+ } +} + +#[derive(Clone)] +struct NotPartialEq(u32); + +#[autoprops] +#[function_component] +fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { + drop(stuff); + html! { +

+ } +} + +#[autoprops] +#[function_component] +fn InvalidFieldName(_: u32) -> Html { + html! { +

+ } +} + +fn main() {} diff --git a/tests/function_component_attr/autoprops-fail.stderr b/tests/function_component_attr/autoprops-fail.stderr new file mode 100644 index 0000000..d68f091 --- /dev/null +++ b/tests/function_component_attr/autoprops-fail.stderr @@ -0,0 +1,59 @@ +error: function components can't accept a receiver + --> tests/function_component_attr/autoprops-fail.rs:6:23 + | +6 | fn CantAcceptReceiver(&self, b: bool) -> Html { + | ^^^^^ + +error: could not find #[function_component] attribute in function declaration (#[autoprops] must be placed *before* #[function_component]) + --> tests/function_component_attr/autoprops-fail.rs:13:1 + | +13 | fn not_a_function_component(b: bool) -> Html { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: expected a reference to a `Properties` type (try: `&bool`) + --> tests/function_component_attr/autoprops-fail.rs:21:25 + | +21 | fn wrong_attrs_order(b: bool) -> Html { + | ^^^^ + +error: expected identifier, found keyword `let` + --> tests/function_component_attr/autoprops-fail.rs:28:22 + | +28 | #[function_component(let)] + | ^^^ + +error: cannot use `_` as field name + --> tests/function_component_attr/autoprops-fail.rs:61:21 + | +61 | fn InvalidFieldName(_: u32) -> Html { + | ^ + +error[E0277]: the trait bound `NotClonable: Clone` is not satisfied + --> tests/function_component_attr/autoprops-fail.rs:40:19 + | +38 | #[autoprops] + | ------------ required by a bound introduced by this call +39 | #[function_component] +40 | fn TypeIsNotClone(stuff: NotClonable) -> Html { + | ^^^^^ the trait `Clone` is not implemented for `NotClonable` + | +help: consider annotating `NotClonable` with `#[derive(Clone)]` + | +36 | #[derive(Clone)] + | + +error[E0369]: binary operation `==` cannot be applied to type `NotPartialEq` + --> tests/function_component_attr/autoprops-fail.rs:52:30 + | +52 | fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { + | ^^^^^^^^^^^^ + | +note: an implementation of `PartialEq<_>` might be missing for `NotPartialEq` + --> tests/function_component_attr/autoprops-fail.rs:48:1 + | +48 | struct NotPartialEq(u32); + | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` +help: consider annotating `NotPartialEq` with `#[derive(PartialEq)]` + | +48 | #[derive(PartialEq)] + | diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs new file mode 100644 index 0000000..50ec504 --- /dev/null +++ b/tests/function_component_attr/autoprops-pass.rs @@ -0,0 +1,112 @@ +#![no_implicit_prelude] + +// Shadow primitives +#[allow(non_camel_case_types)] +pub struct bool; +#[allow(non_camel_case_types)] +pub struct char; +#[allow(non_camel_case_types)] +pub struct f32; +#[allow(non_camel_case_types)] +pub struct f64; +#[allow(non_camel_case_types)] +pub struct i128; +#[allow(non_camel_case_types)] +pub struct i16; +#[allow(non_camel_case_types)] +pub struct i32; +#[allow(non_camel_case_types)] +pub struct i64; +#[allow(non_camel_case_types)] +pub struct i8; +#[allow(non_camel_case_types)] +pub struct isize; +#[allow(non_camel_case_types)] +pub struct str; +#[allow(non_camel_case_types)] +pub struct u128; +#[allow(non_camel_case_types)] +pub struct u16; +#[allow(non_camel_case_types)] +pub struct u32; +#[allow(non_camel_case_types)] +pub struct u64; +#[allow(non_camel_case_types)] +pub struct u8; +#[allow(non_camel_case_types)] +pub struct usize; + +#[::yew_autoprops::autoprops] +#[::yew::function_component] +fn CompUseFnName() -> ::yew::Html +{ + ::yew::html! { +

+ } +} + +#[::yew_autoprops::autoprops] +#[::yew::function_component(CompNoProperties)] +fn comp_no_properties() -> ::yew::Html +{ + ::yew::html! { +

+ } +} + +#[::yew_autoprops::autoprops] +#[::yew::function_component(CompNoGenerics)] +fn comp_no_generics(#[prop_or_default] b: ::std::primitive::bool, a: &::yew::AttrValue) -> ::yew::Html +{ + let _: ::std::primitive::bool = b; + let _: &::yew::AttrValue = a; + ::yew::html! { +

+ } +} + +#[::yew_autoprops::autoprops] +#[::yew::function_component(CompGenerics)] +fn comp_generics(b: T1, a: &T2) -> ::yew::Html +where + T1: ::std::cmp::PartialEq + ::std::clone::Clone, + T2: ::std::cmp::PartialEq, +{ + let _: T1 = b; + let _: &T2 = a; + ::yew::html! { +

+ } +} + +#[::yew_autoprops::autoprops] +#[::yew::function_component(CompGenericsWithoutField)] +fn comp_generics_without_field(b: ::std::primitive::bool) -> ::yew::Html { + let _ = b; + ::yew::html! { +

+ } +} + +#[::yew_autoprops::autoprops] +#[::yew::function_component(ConstGenerics)] +fn const_generics(xs: [::std::primitive::u32; N]) -> ::yew::Html { + let _: [::std::primitive::u32; N] = xs; + ::yew::html! { +
+ { N } +
+ } +} + +fn compile_pass() { + let _ = ::yew::html! { }; + let _ = ::yew::html! { }; + let _ = ::yew::html! { }; + let _ = ::yew::html! { }; + let _ = ::yew::html! { b=true a="foo" /> }; + + let _ = ::yew::html! { xs={[1_u32, 2_u32]} /> }; +} + +fn main() {} diff --git a/tests/test.rs b/tests/test.rs deleted file mode 100644 index bc7edaa..0000000 --- a/tests/test.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[test] -fn tests() { - let t = trybuild::TestCases::new(); - t.pass("tests/cases/*-pass.rs"); - t.compile_fail("tests/cases/*-fail.rs"); -} From c3e88fabfedf0852c01ef3beb810b4b3336c67a9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:09:51 +0100 Subject: [PATCH 02/21] Remove useless step in the workflow --- .github/workflows/rust.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index c33adf7..fceb1a5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -20,5 +20,4 @@ jobs: steps: - uses: actions/checkout@v3 - run: rustup default ${{ matrix.rust }} - - run: cargo build --verbose - run: cargo test --verbose From 3af623683295801f8aab7159799fd858f0e5d5a9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:14:39 +0100 Subject: [PATCH 03/21] Add caching in the CI workflow --- .github/workflows/rust.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index fceb1a5..2e6357a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,5 +19,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 - run: rustup default ${{ matrix.rust }} - run: cargo test --verbose From a1c7fb385eb084e5013010b592287042bb8fb212 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:15:27 +0100 Subject: [PATCH 04/21] Force adding Cargo.lock --- .gitignore | 3 +- Cargo.lock | 1225 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1226 insertions(+), 2 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 86badbd..7647dfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /target output.log -Cargo.lock .envrc -.aider* \ No newline at end of file +.aider* diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..edf412f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1225 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anymap2" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "basic-toml" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" +dependencies = [ + "serde", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "boolinator" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "bytes" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" + +[[package]] +name = "futures-io" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" + +[[package]] +name = "futures-macro" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + +[[package]] +name = "futures-task" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" + +[[package]] +name = "futures-util" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "gloo" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" +dependencies = [ + "gloo-console 0.2.3", + "gloo-dialogs 0.1.1", + "gloo-events 0.1.2", + "gloo-file 0.2.3", + "gloo-history 0.1.5", + "gloo-net 0.3.1", + "gloo-render 0.1.1", + "gloo-storage 0.2.2", + "gloo-timers 0.2.6", + "gloo-utils 0.1.7", + "gloo-worker 0.2.1", +] + +[[package]] +name = "gloo" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd35526c28cc55c1db77aed6296de58677dbab863b118483a27845631d870249" +dependencies = [ + "gloo-console 0.3.0", + "gloo-dialogs 0.2.0", + "gloo-events 0.2.0", + "gloo-file 0.3.0", + "gloo-history 0.2.1", + "gloo-net 0.4.0", + "gloo-render 0.2.0", + "gloo-storage 0.3.0", + "gloo-timers 0.3.0", + "gloo-utils 0.2.0", + "gloo-worker 0.4.0", +] + +[[package]] +name = "gloo-console" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" +dependencies = [ + "gloo-utils 0.1.7", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-console" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" +dependencies = [ + "gloo-utils 0.2.0", + "js-sys", + "serde", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-dialogs" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-dialogs" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4748e10122b01435750ff530095b1217cf6546173459448b83913ebe7815df" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-events" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-events" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c26fb45f7c385ba980f5fa87ac677e363949e065a083722697ef1b2cc91e41" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-file" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" +dependencies = [ + "gloo-events 0.1.2", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-file" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" +dependencies = [ + "gloo-events 0.2.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" +dependencies = [ + "gloo-events 0.1.2", + "gloo-utils 0.1.7", + "serde", + "serde-wasm-bindgen 0.5.0", + "serde_urlencoded", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-history" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4022e82f5f9e03cb1251b13c0a967e0600e97aa179c617f6519bac40640160" +dependencies = [ + "getrandom", + "gloo-events 0.2.0", + "gloo-utils 0.2.0", + "serde", + "serde-wasm-bindgen 0.6.1", + "serde_urlencoded", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils 0.1.7", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-net" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils 0.2.0", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-render" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-render" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56008b6744713a8e8d98ac3dcb7d06543d5662358c9c805b4ce2167ad4649833" +dependencies = [ + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-storage" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" +dependencies = [ + "gloo-utils 0.1.7", + "js-sys", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-storage" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" +dependencies = [ + "gloo-utils 0.2.0", + "js-sys", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" +dependencies = [ + "anymap2", + "bincode", + "gloo-console 0.2.3", + "gloo-utils 0.1.7", + "js-sys", + "serde", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-worker" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" +dependencies = [ + "bincode", + "futures", + "gloo-utils 0.2.0", + "gloo-worker-macros", + "js-sys", + "pinned", + "serde", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-worker-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956caa58d4857bc9941749d55e4bd3000032d8212762586fa5705632967140e7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + +[[package]] +name = "hermit-abi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "implicit-clone" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "789a53d49d2276908b1fcccb9dfcf65c7a6e884c1df639f26aeff4f142b3ef9e" +dependencies = [ + "indexmap", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memchr" +version = "2.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pinned" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a829027bd95e54cfe13e3e258a1ae7b645960553fb82b75ff852c29688ee595b" +dependencies = [ + "futures", + "rustversion", + "thiserror", +] + +[[package]] +name = "prettyplease" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +dependencies = [ + "proc-macro2", + "syn 2.0.38", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prokio" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" +dependencies = [ + "futures", + "gloo 0.8.1", + "num_cpus", + "once_cell", + "pin-project", + "pinned", + "tokio", + "tokio-stream", + "wasm-bindgen-futures", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + +[[package]] +name = "ryu" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" + +[[package]] +name = "serde" +version = "1.0.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ba92964781421b6cef36bf0d7da26d201e96d84e1b10e7ae6ed416e516906d" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.190" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "serde_json" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tokio" +version = "1.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +dependencies = [ + "backtrace", + "pin-project-lite", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" + +[[package]] +name = "toml_edit" +version = "0.19.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trybuild" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "196a58260a906cedb9bf6d8034b6379d0c11f552416960452f267402ceeddff1" +dependencies = [ + "basic-toml", + "glob", + "once_cell", + "serde", + "serde_derive", + "serde_json", + "termcolor", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "winnow" +version = "0.5.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +dependencies = [ + "memchr", +] + +[[package]] +name = "yew" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" +dependencies = [ + "console_error_panic_hook", + "futures", + "gloo 0.10.0", + "implicit-clone", + "indexmap", + "js-sys", + "prokio", + "rustversion", + "serde", + "slab", + "thiserror", + "tokio", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "yew-macro", +] + +[[package]] +name = "yew-autoprops" +version = "0.3.0" +dependencies = [ + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.38", + "trybuild", + "yew", +] + +[[package]] +name = "yew-macro" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" +dependencies = [ + "boolinator", + "once_cell", + "prettyplease", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.38", +] From 0fc2002ad7d6f974f6d28a897b158c912be7cbe8 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:25:51 +0100 Subject: [PATCH 05/21] Forgot to update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c6217e6..731afc6 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,11 @@ No more extra one-off Props structs! # Examples ```rust -use yew_autoprops::autoprops_component; +use yew_autoprops::autoprops; use yew::prelude::*; -#[autoprops_component] +#[autoprops] +#[function_component] fn CoolComponent(#[prop_or_default] hidden: bool, smth: &AttrValue) -> Html { html! {
@@ -24,10 +25,11 @@ fn CoolComponent(#[prop_or_default] hidden: bool, smth: &AttrValue) -> Html { ``` ```rust -use yew_autoprops::autoprops_component; +use yew_autoprops::autoprops; use yew::prelude::*; -#[autoprops_component(CoolComponent)] +#[autoprops(CoolComponentProps)] +#[function_component(CoolComponent)] fn cool_component(#[prop_or_default] hidden: bool, smth: &AttrValue) -> Html { html! {
From 388d0182e1409cb79df194acf2e65d023c1de043 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:33:45 +0100 Subject: [PATCH 06/21] Make passing test run on any version of Rust --- tests/function_attr_test.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/function_attr_test.rs b/tests/function_attr_test.rs index ed3cf9d..0c4d894 100644 --- a/tests/function_attr_test.rs +++ b/tests/function_attr_test.rs @@ -1,7 +1,13 @@ #[allow(dead_code)] -#[rustversion::attr(stable(1.64), test)] -fn tests() { +#[test] +fn tests_pass() { let t = trybuild::TestCases::new(); t.pass("tests/function_component_attr/*-pass.rs"); +} + +#[allow(dead_code)] +#[rustversion::attr(stable(1.64), test)] +fn tests_fail() { + let t = trybuild::TestCases::new(); t.compile_fail("tests/function_component_attr/*-fail.rs"); } From f2995ed0450fc78ca9c62946cbbe44a4c9abc9c1 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:35:05 +0100 Subject: [PATCH 07/21] Add cache key on Rust version to differentiate both jobs --- .github/workflows/rust.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2e6357a..d166573 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -20,5 +20,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 + with: + key: rust-${{ matrix.rust }} - run: rustup default ${{ matrix.rust }} - run: cargo test --verbose From 15269d43ff9eba716f05819c0f88054188dc2098 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:54:30 +0100 Subject: [PATCH 08/21] Trigger CI From 7ff4375b06a24ac46cc631c91294f1abc5eba63b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 10:58:44 +0100 Subject: [PATCH 09/21] Fix issue with single generic and add test --- src/autoprops.rs | 6 +++--- tests/function_component_attr/autoprops-pass.rs | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index b0b3e69..d61591b 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -119,18 +119,18 @@ impl Autoprops { .inputs .iter() .filter_map(|arg| match arg { - syn::FnArg::Typed(syn::PatType { pat, .. }) => Some(quote! { #pat }), + syn::FnArg::Typed(syn::PatType { pat, .. }) => Some(quote! { #pat, }), _ => None, }) .collect::>(); let phantom = sig.generics.type_params().next().is_some().then(|| { quote! { - , phantom: _ + phantom: _, } }); quote! { #(#receivers,)* #properties_name { - #(#args),* + #(#args)* #phantom }: &#properties_name #type_generics } diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index 50ec504..33b1a1b 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -65,6 +65,14 @@ fn comp_no_generics(#[prop_or_default] b: ::std::primitive::bool, a: &::yew::Att } } +#[::yew_autoprops::autoprops] +#[::yew::function_component(CompSingleGeneric)] +fn comp_single_generic() -> ::yew::Html { + ::yew::html! { +

+ } +} + #[::yew_autoprops::autoprops] #[::yew::function_component(CompGenerics)] fn comp_generics(b: T1, a: &T2) -> ::yew::Html From cd000651839dad3f57d947004e2beb5c9eb8d1b6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 11:18:27 +0100 Subject: [PATCH 10/21] Fix for private fields & add test --- src/autoprops.rs | 6 +++--- tests/function_component_attr/autoprops-pass.rs | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index d61591b..e63e521 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -174,9 +174,9 @@ impl Autoprops { .filter_map(|arg| match arg { syn::FnArg::Typed(syn::PatType { attrs, pat, ty, .. }) => match ty.as_ref() { syn::Type::Reference(syn::TypeReference { elem, .. }) => { - Some(quote! { #(#attrs)* #pat: #elem, }) + Some(quote! { #(#attrs)* #vis #pat: #elem, }) } - _ => Some(quote! { #(#attrs)* #pat: #ty, }), + _ => Some(quote! { #(#attrs)* #vis #pat: #ty, }), }, _ => None, }) @@ -189,7 +189,7 @@ impl Autoprops { let phantom = (!type_params.is_empty()).then(|| { quote! { #[prop_or_default] - phantom: ::std::marker::PhantomData <( #(#type_params),* )>, + #vis phantom: ::std::marker::PhantomData <( #(#type_params),* )>, } }); let fields_eq = sig diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index 33b1a1b..c046aa0 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -107,14 +107,29 @@ fn const_generics(xs: [::std::primitive::u32; } } +mod private_module { + #[::yew_autoprops::autoprops] + #[::yew::function_component(CompPrivateTest)] + pub fn comp_private_test(#[prop_or_default] b: ::std::primitive::bool) -> ::yew::Html + { + let _: ::std::primitive::bool = b; + ::yew::html! { +

+ } + } +} + +use private_module::*; + fn compile_pass() { let _ = ::yew::html! { }; let _ = ::yew::html! { }; let _ = ::yew::html! { }; let _ = ::yew::html! { }; + let _ = ::yew::html! { /> }; let _ = ::yew::html! { b=true a="foo" /> }; - let _ = ::yew::html! { xs={[1_u32, 2_u32]} /> }; + let _ = ::yew::html! { }; } fn main() {} From 27427cca11dc8a0c7f9b7e38eefb2baf9dbffc59 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 11:21:50 +0100 Subject: [PATCH 11/21] Also add failing test for private components --- .../function_component_attr/autoprops-fail.rs | 19 ++++++++++++++++++- .../autoprops-fail.stderr | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/function_component_attr/autoprops-fail.rs b/tests/function_component_attr/autoprops-fail.rs index 36f1f70..4e90f63 100644 --- a/tests/function_component_attr/autoprops-fail.rs +++ b/tests/function_component_attr/autoprops-fail.rs @@ -64,4 +64,21 @@ fn InvalidFieldName(_: u32) -> Html { } } -fn main() {} +mod private_module { + #[::yew_autoprops::autoprops] + #[::yew::function_component(CompPrivateTest)] + fn comp_private_test(#[prop_or_default] b: ::std::primitive::bool) -> ::yew::Html + { + let _: ::std::primitive::bool = b; + ::yew::html! { +

+ } + } +} + +#[allow(unused_imports)] +use private_module::*; + +fn main() { + let _ = html! { }; +} diff --git a/tests/function_component_attr/autoprops-fail.stderr b/tests/function_component_attr/autoprops-fail.stderr index d68f091..d87685c 100644 --- a/tests/function_component_attr/autoprops-fail.stderr +++ b/tests/function_component_attr/autoprops-fail.stderr @@ -28,6 +28,19 @@ error: cannot use `_` as field name 61 | fn InvalidFieldName(_: u32) -> Html { | ^ +error[E0412]: cannot find type `CompPrivateTest` in this scope + --> tests/function_component_attr/autoprops-fail.rs:83:22 + | +83 | let _ = html! { }; + | ^^^^^^^^^^^^^^^ not found in this scope + | +note: struct `crate::private_module::CompPrivateTest` exists but is inaccessible + --> tests/function_component_attr/autoprops-fail.rs:69:5 + | +69 | #[::yew::function_component(CompPrivateTest)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible + = note: this error originates in the attribute macro `::yew::function_component` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0277]: the trait bound `NotClonable: Clone` is not satisfied --> tests/function_component_attr/autoprops-fail.rs:40:19 | From e64e1164f70034d31ad1efec1824ece64bb448a9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 11:54:09 +0100 Subject: [PATCH 12/21] Preserve return type --- src/autoprops.rs | 3 ++- tests/function_component_attr/autoprops-pass.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index e63e521..f9306ac 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -149,10 +149,11 @@ impl Autoprops { _ => None, }) .collect::>(); + let output = &sig.output; quote! { #(#attrs)* - #vis fn #fn_name #impl_generics (#inputs) -> ::yew::Html #where_clause { + #vis fn #fn_name #impl_generics (#inputs) #output #where_clause { #(#clones)* #block } diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index c046aa0..2c15365 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -121,6 +121,15 @@ mod private_module { use private_module::*; +#[::yew_autoprops::autoprops] +#[::yew::function_component] +fn CompHtmlResult() -> ::yew::HtmlResult +{ + ::std::result::Result::Ok(::yew::html! { +

+ }) +} + fn compile_pass() { let _ = ::yew::html! { }; let _ = ::yew::html! { }; @@ -130,6 +139,7 @@ fn compile_pass() { let _ = ::yew::html! { b=true a="foo" /> }; let _ = ::yew::html! { xs={[1_u32, 2_u32]} /> }; let _ = ::yew::html! { }; + let _ = ::yew::html! { }; } fn main() {} From 00718cdba9f9b9756614509f7f4567a8e84db1ca Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 12:23:51 +0100 Subject: [PATCH 13/21] Fix generics with default not working --- src/autoprops.rs | 8 +++++--- tests/function_component_attr/autoprops-pass.rs | 11 +++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index f9306ac..f606e75 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -103,7 +103,7 @@ impl Autoprops { } = &self.item_fn; let fn_name = &sig.ident; - let (impl_generics, type_generics, where_clause) = sig.generics.split_for_impl(); + let (_impl_generics, type_generics, where_clause) = sig.generics.split_for_impl(); let inputs = if self.needs_a_properties_struct() { // NOTE: function components currently don't accept receivers, we're just passing the // information to the next macro to fail and give its own error message @@ -150,10 +150,11 @@ impl Autoprops { }) .collect::>(); let output = &sig.output; + let impl_generics_with_defaults = &sig.generics; quote! { #(#attrs)* - #vis fn #fn_name #impl_generics (#inputs) #output #where_clause { + #vis fn #fn_name #impl_generics_with_defaults (#inputs) #output #where_clause { #(#clones)* #block } @@ -203,10 +204,11 @@ impl Autoprops { _ => None, }) .collect::>(); + let impl_generics_with_defaults = &sig.generics; quote! { #[derive(::yew::Properties)] - #vis struct #properties_name #impl_generics #where_clause { + #vis struct #properties_name #impl_generics_with_defaults #where_clause { #(#fields)* #phantom } diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index 2c15365..1454438 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -130,6 +130,15 @@ fn CompHtmlResult() -> ::yew::HtmlResult }) } +#[::yew_autoprops::autoprops] +#[::yew::function_component] +fn CompWithDefaultGeneric() -> ::yew::Html +{ + ::yew::html! { +

+ } +} + fn compile_pass() { let _ = ::yew::html! { }; let _ = ::yew::html! { }; @@ -140,6 +149,8 @@ fn compile_pass() { let _ = ::yew::html! { xs={[1_u32, 2_u32]} /> }; let _ = ::yew::html! { }; let _ = ::yew::html! { }; + let _ = ::yew::html! { }; + let _ = ::yew::html! { /> }; } fn main() {} From b60e5cc05abd4979d9c8a58a6a1689b9ca233540 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 12:31:08 +0100 Subject: [PATCH 14/21] Just making sure the where_clause is not pushed unexpectedly --- tests/function_component_attr/autoprops-pass.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index 1454438..7715a4f 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -123,8 +123,7 @@ use private_module::*; #[::yew_autoprops::autoprops] #[::yew::function_component] -fn CompHtmlResult() -> ::yew::HtmlResult -{ +fn CompHtmlResult() -> ::yew::HtmlResult { ::std::result::Result::Ok(::yew::html! {

}) @@ -133,7 +132,10 @@ fn CompHtmlResult() -> ::yew::HtmlResult #[::yew_autoprops::autoprops] #[::yew::function_component] fn CompWithDefaultGeneric() -> ::yew::Html +where + T: ::std::default::Default, { + let _ = T::default(); ::yew::html! {

} @@ -150,7 +152,7 @@ fn compile_pass() { let _ = ::yew::html! { }; let _ = ::yew::html! { }; let _ = ::yew::html! { }; - let _ = ::yew::html! { /> }; + let _ = ::yew::html! { /> }; } fn main() {} From 248b0c2c3c54889a690688c7cbb1a48ebf21f5d4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 15:55:13 +0100 Subject: [PATCH 15/21] use format_ident!() --- src/autoprops.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index f606e75..82e5aca 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -74,10 +74,7 @@ impl syn::parse::Parse for Autoprops { } } - let properties_name = syn::Ident::new( - &format!("{}Props", component_name), - proc_macro2::Span::call_site(), - ); + let properties_name = quote::format_ident!("{}Props", component_name); Ok(Self { properties_name, From ff74446ed11f21efde3387e7a1d3d07eda26a33f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 5 Nov 2023 17:13:44 +0100 Subject: [PATCH 16/21] Do not create props struct if there are only generic arguments --- src/autoprops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index 82e5aca..dd0a1d5 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -221,7 +221,7 @@ impl Autoprops { fn needs_a_properties_struct(&self) -> bool { let syn::ItemFn { sig, .. } = &self.item_fn; - !sig.inputs.is_empty() || sig.generics.type_params().next().is_some() + !sig.inputs.is_empty() } } From 45682ccf36f4df3bed3e71b1a1c076bb1d85f50c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Nov 2023 15:16:43 +0100 Subject: [PATCH 17/21] Ensure cloned types impl ImplicitClone --- Cargo.lock | 5 +- Cargo.toml | 7 ++- src/autoprops.rs | 4 +- .../function_component_attr/autoprops-fail.rs | 3 + .../autoprops-fail.stderr | 56 +++++++++---------- .../function_component_attr/autoprops-pass.rs | 2 +- 6 files changed, 42 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index edf412f..92aa796 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -600,9 +600,9 @@ dependencies = [ [[package]] name = "implicit-clone" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789a53d49d2276908b1fcccb9dfcf65c7a6e884c1df639f26aeff4f142b3ef9e" +checksum = "7a50fed6f6aa778e7946f697a88e474b4b4a83fb0849cec1ac65fa8e869319dd" dependencies = [ "indexmap", ] @@ -1201,6 +1201,7 @@ dependencies = [ name = "yew-autoprops" version = "0.3.0" dependencies = [ + "implicit-clone", "proc-macro2", "quote", "rustversion", diff --git a/Cargo.toml b/Cargo.toml index 7a1d4e6..5140745 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ [dev-dependencies] - yew = { version = "0.21" } - trybuild = "1" - rustversion = "1" + yew = { version = "0.21" } + implicit-clone = "0.4.6" + trybuild = "1" + rustversion = "1" diff --git a/src/autoprops.rs b/src/autoprops.rs index dd0a1d5..c206c0f 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -141,7 +141,9 @@ impl Autoprops { syn::FnArg::Typed(syn::PatType { pat, ty, .. }) if !matches!(**ty, syn::Type::Reference(_)) => { - Some(quote! { let #pat = ::std::clone::Clone::clone(#pat); }) + Some(quote! { + let #pat = ::implicit_clone::ImplicitClone::implicit_clone(#pat); + }) } _ => None, }) diff --git a/tests/function_component_attr/autoprops-fail.rs b/tests/function_component_attr/autoprops-fail.rs index 4e90f63..f8d98ad 100644 --- a/tests/function_component_attr/autoprops-fail.rs +++ b/tests/function_component_attr/autoprops-fail.rs @@ -1,4 +1,5 @@ use yew::prelude::*; +use yew::html::ImplicitClone; use yew_autoprops::*; #[autoprops] @@ -47,6 +48,8 @@ fn TypeIsNotClone(stuff: NotClonable) -> Html { #[derive(Clone)] struct NotPartialEq(u32); +impl ImplicitClone for NotPartialEq {} + #[autoprops] #[function_component] fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { diff --git a/tests/function_component_attr/autoprops-fail.stderr b/tests/function_component_attr/autoprops-fail.stderr index d87685c..e8394c1 100644 --- a/tests/function_component_attr/autoprops-fail.stderr +++ b/tests/function_component_attr/autoprops-fail.stderr @@ -1,72 +1,72 @@ error: function components can't accept a receiver - --> tests/function_component_attr/autoprops-fail.rs:6:23 + --> tests/function_component_attr/autoprops-fail.rs:7:23 | -6 | fn CantAcceptReceiver(&self, b: bool) -> Html { +7 | fn CantAcceptReceiver(&self, b: bool) -> Html { | ^^^^^ error: could not find #[function_component] attribute in function declaration (#[autoprops] must be placed *before* #[function_component]) - --> tests/function_component_attr/autoprops-fail.rs:13:1 + --> tests/function_component_attr/autoprops-fail.rs:14:1 | -13 | fn not_a_function_component(b: bool) -> Html { +14 | fn not_a_function_component(b: bool) -> Html { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: expected a reference to a `Properties` type (try: `&bool`) - --> tests/function_component_attr/autoprops-fail.rs:21:25 + --> tests/function_component_attr/autoprops-fail.rs:22:25 | -21 | fn wrong_attrs_order(b: bool) -> Html { +22 | fn wrong_attrs_order(b: bool) -> Html { | ^^^^ error: expected identifier, found keyword `let` - --> tests/function_component_attr/autoprops-fail.rs:28:22 + --> tests/function_component_attr/autoprops-fail.rs:29:22 | -28 | #[function_component(let)] +29 | #[function_component(let)] | ^^^ error: cannot use `_` as field name - --> tests/function_component_attr/autoprops-fail.rs:61:21 + --> tests/function_component_attr/autoprops-fail.rs:64:21 | -61 | fn InvalidFieldName(_: u32) -> Html { +64 | fn InvalidFieldName(_: u32) -> Html { | ^ error[E0412]: cannot find type `CompPrivateTest` in this scope - --> tests/function_component_attr/autoprops-fail.rs:83:22 + --> tests/function_component_attr/autoprops-fail.rs:86:22 | -83 | let _ = html! { }; +86 | let _ = html! { }; | ^^^^^^^^^^^^^^^ not found in this scope | note: struct `crate::private_module::CompPrivateTest` exists but is inaccessible - --> tests/function_component_attr/autoprops-fail.rs:69:5 + --> tests/function_component_attr/autoprops-fail.rs:72:5 | -69 | #[::yew::function_component(CompPrivateTest)] +72 | #[::yew::function_component(CompPrivateTest)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible = note: this error originates in the attribute macro `::yew::function_component` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0277]: the trait bound `NotClonable: Clone` is not satisfied - --> tests/function_component_attr/autoprops-fail.rs:40:19 +error[E0277]: the trait bound `NotClonable: ImplicitClone` is not satisfied + --> tests/function_component_attr/autoprops-fail.rs:41:19 | -38 | #[autoprops] +39 | #[autoprops] | ------------ required by a bound introduced by this call -39 | #[function_component] -40 | fn TypeIsNotClone(stuff: NotClonable) -> Html { - | ^^^^^ the trait `Clone` is not implemented for `NotClonable` +40 | #[function_component] +41 | fn TypeIsNotClone(stuff: NotClonable) -> Html { + | ^^^^^ expected an implementor of trait `ImplicitClone` | -help: consider annotating `NotClonable` with `#[derive(Clone)]` - | -36 | #[derive(Clone)] +help: consider borrowing here | +41 | fn TypeIsNotClone(&stuff: NotClonable) -> Html { + | + error[E0369]: binary operation `==` cannot be applied to type `NotPartialEq` - --> tests/function_component_attr/autoprops-fail.rs:52:30 + --> tests/function_component_attr/autoprops-fail.rs:55:30 | -52 | fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { +55 | fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { | ^^^^^^^^^^^^ | note: an implementation of `PartialEq<_>` might be missing for `NotPartialEq` - --> tests/function_component_attr/autoprops-fail.rs:48:1 + --> tests/function_component_attr/autoprops-fail.rs:49:1 | -48 | struct NotPartialEq(u32); +49 | struct NotPartialEq(u32); | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` help: consider annotating `NotPartialEq` with `#[derive(PartialEq)]` | -48 | #[derive(PartialEq)] +49 | #[derive(PartialEq)] | diff --git a/tests/function_component_attr/autoprops-pass.rs b/tests/function_component_attr/autoprops-pass.rs index 7715a4f..45ca1d9 100644 --- a/tests/function_component_attr/autoprops-pass.rs +++ b/tests/function_component_attr/autoprops-pass.rs @@ -77,7 +77,7 @@ fn comp_single_generic() -> ::yew::Html { #[::yew::function_component(CompGenerics)] fn comp_generics(b: T1, a: &T2) -> ::yew::Html where - T1: ::std::cmp::PartialEq + ::std::clone::Clone, + T1: ::std::cmp::PartialEq + ::implicit_clone::ImplicitClone, T2: ::std::cmp::PartialEq, { let _: T1 = b; From 686f0099fd1616b1ad53bb001569f9009c2f96f5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Nov 2023 17:04:19 +0100 Subject: [PATCH 18/21] It doesn't look like I need this --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 58f086e..7440107 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,6 @@ mod function_component; use quote::ToTokens; -//#[proc_macro_error::proc_macro_error] #[proc_macro_attribute] pub fn autoprops( attr: proc_macro::TokenStream, From ad7c72a5c471cba90f85df76f97b89bf07849f3c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Thu, 9 Nov 2023 17:06:36 +0100 Subject: [PATCH 19/21] Use ImplicitClone re-export from Yew --- src/autoprops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index c206c0f..024b484 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -142,7 +142,7 @@ impl Autoprops { if !matches!(**ty, syn::Type::Reference(_)) => { Some(quote! { - let #pat = ::implicit_clone::ImplicitClone::implicit_clone(#pat); + let #pat = ::yew::html::ImplicitClone::implicit_clone(#pat); }) } _ => None, From e323bee7ee2a675e2610db67f3a8a0e77b7280ce Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Mon, 13 Nov 2023 08:52:56 +0100 Subject: [PATCH 20/21] Rename field phantom to __yew_autoprops_phantom --- src/autoprops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index 024b484..5126a7b 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -122,7 +122,7 @@ impl Autoprops { .collect::>(); let phantom = sig.generics.type_params().next().is_some().then(|| { quote! { - phantom: _, + __yew_autoprops_phantom: _, } }); quote! { @@ -190,7 +190,7 @@ impl Autoprops { let phantom = (!type_params.is_empty()).then(|| { quote! { #[prop_or_default] - #vis phantom: ::std::marker::PhantomData <( #(#type_params),* )>, + #vis __yew_autoprops_phantom: ::std::marker::PhantomData <( #(#type_params),* )>, } }); let fields_eq = sig From e8fe2f0bc0adb24bc6e43d6877fdf56610dd647a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Mon, 13 Nov 2023 08:57:02 +0100 Subject: [PATCH 21/21] Remove check for #[function_component] --- src/autoprops.rs | 43 +++++------------ .../function_component_attr/autoprops-fail.rs | 7 --- .../autoprops-fail.stderr | 46 ++++++++----------- 3 files changed, 32 insertions(+), 64 deletions(-) diff --git a/src/autoprops.rs b/src/autoprops.rs index 5126a7b..d62ba7b 100644 --- a/src/autoprops.rs +++ b/src/autoprops.rs @@ -26,42 +26,23 @@ impl syn::parse::Parse for Autoprops { let mut component_name = item_fn.sig.ident.clone(); - attrs - .iter() - .find(|attr| { - match &attr.meta { - syn::Meta::Path(path) => { - if let Some(last_segment) = path.segments.last() { - if last_segment.ident == "function_component" { - return true; - } - } - } - syn::Meta::List(syn::MetaList { path, tokens, .. }) => { - if let Some(last_segment) = path.segments.last() { - if last_segment.ident == "function_component" { - if let Ok(attr) = - syn::parse2::(tokens.clone()) - { - if let Some(name) = attr.component_name { - component_name = name; - } + for attr in attrs { + match &attr.meta { + syn::Meta::List(syn::MetaList { path, tokens, .. }) => { + if let Some(last_segment) = path.segments.last() { + if last_segment.ident == "function_component" { + if let Ok(attr) = syn::parse2::(tokens.clone()) { + if let Some(name) = attr.component_name { + component_name = name; } - return true; } + break; } } - _ => {} } - false - }) - .ok_or_else(|| { - syn::Error::new_spanned( - sig, - "could not find #[function_component] attribute in function declaration \ - (#[autoprops] must be placed *before* #[function_component])", - ) - })?; + _ => {} + } + } for input in &sig.inputs { if let syn::FnArg::Typed(syn::PatType { pat, .. }) = input { diff --git a/tests/function_component_attr/autoprops-fail.rs b/tests/function_component_attr/autoprops-fail.rs index f8d98ad..f426292 100644 --- a/tests/function_component_attr/autoprops-fail.rs +++ b/tests/function_component_attr/autoprops-fail.rs @@ -10,13 +10,6 @@ fn CantAcceptReceiver(&self, b: bool) -> Html { } } -#[autoprops] -fn not_a_function_component(b: bool) -> Html { - html! { -

{b}

- } -} - #[function_component(WrongAttrsOrder)] #[autoprops] fn wrong_attrs_order(b: bool) -> Html { diff --git a/tests/function_component_attr/autoprops-fail.stderr b/tests/function_component_attr/autoprops-fail.stderr index e8394c1..1d23b88 100644 --- a/tests/function_component_attr/autoprops-fail.stderr +++ b/tests/function_component_attr/autoprops-fail.stderr @@ -4,69 +4,63 @@ error: function components can't accept a receiver 7 | fn CantAcceptReceiver(&self, b: bool) -> Html { | ^^^^^ -error: could not find #[function_component] attribute in function declaration (#[autoprops] must be placed *before* #[function_component]) - --> tests/function_component_attr/autoprops-fail.rs:14:1 - | -14 | fn not_a_function_component(b: bool) -> Html { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: expected a reference to a `Properties` type (try: `&bool`) - --> tests/function_component_attr/autoprops-fail.rs:22:25 + --> tests/function_component_attr/autoprops-fail.rs:15:25 | -22 | fn wrong_attrs_order(b: bool) -> Html { +15 | fn wrong_attrs_order(b: bool) -> Html { | ^^^^ error: expected identifier, found keyword `let` - --> tests/function_component_attr/autoprops-fail.rs:29:22 + --> tests/function_component_attr/autoprops-fail.rs:22:22 | -29 | #[function_component(let)] +22 | #[function_component(let)] | ^^^ error: cannot use `_` as field name - --> tests/function_component_attr/autoprops-fail.rs:64:21 + --> tests/function_component_attr/autoprops-fail.rs:57:21 | -64 | fn InvalidFieldName(_: u32) -> Html { +57 | fn InvalidFieldName(_: u32) -> Html { | ^ error[E0412]: cannot find type `CompPrivateTest` in this scope - --> tests/function_component_attr/autoprops-fail.rs:86:22 + --> tests/function_component_attr/autoprops-fail.rs:79:22 | -86 | let _ = html! { }; +79 | let _ = html! { }; | ^^^^^^^^^^^^^^^ not found in this scope | note: struct `crate::private_module::CompPrivateTest` exists but is inaccessible - --> tests/function_component_attr/autoprops-fail.rs:72:5 + --> tests/function_component_attr/autoprops-fail.rs:65:5 | -72 | #[::yew::function_component(CompPrivateTest)] +65 | #[::yew::function_component(CompPrivateTest)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessible = note: this error originates in the attribute macro `::yew::function_component` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `NotClonable: ImplicitClone` is not satisfied - --> tests/function_component_attr/autoprops-fail.rs:41:19 + --> tests/function_component_attr/autoprops-fail.rs:34:19 | -39 | #[autoprops] +32 | #[autoprops] | ------------ required by a bound introduced by this call -40 | #[function_component] -41 | fn TypeIsNotClone(stuff: NotClonable) -> Html { +33 | #[function_component] +34 | fn TypeIsNotClone(stuff: NotClonable) -> Html { | ^^^^^ expected an implementor of trait `ImplicitClone` | help: consider borrowing here | -41 | fn TypeIsNotClone(&stuff: NotClonable) -> Html { +34 | fn TypeIsNotClone(&stuff: NotClonable) -> Html { | + error[E0369]: binary operation `==` cannot be applied to type `NotPartialEq` - --> tests/function_component_attr/autoprops-fail.rs:55:30 + --> tests/function_component_attr/autoprops-fail.rs:48:30 | -55 | fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { +48 | fn TypeIsNotPartialEq(stuff: NotPartialEq) -> Html { | ^^^^^^^^^^^^ | note: an implementation of `PartialEq<_>` might be missing for `NotPartialEq` - --> tests/function_component_attr/autoprops-fail.rs:49:1 + --> tests/function_component_attr/autoprops-fail.rs:42:1 | -49 | struct NotPartialEq(u32); +42 | struct NotPartialEq(u32); | ^^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>` help: consider annotating `NotPartialEq` with `#[derive(PartialEq)]` | -49 | #[derive(PartialEq)] +42 | #[derive(PartialEq)] |