diff --git a/Cargo.lock b/Cargo.lock index 25bb443f..843ce2ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,18 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + [[package]] name = "cgp" version = "0.7.0" @@ -184,6 +196,29 @@ version = "0.7.0" dependencies = [ "cgp-macro-core", "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cgp-macro-test-util" +version = "0.7.0" +dependencies = [ + "cgp-macro-core", + "cgp-macro-lib", + "cgp-macro-test-util-lib", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cgp-macro-test-util-lib" +version = "0.7.0" +dependencies = [ + "cgp-macro-core", + "cgp-macro-lib", "prettyplease", "proc-macro2", "quote", @@ -217,8 +252,9 @@ name = "cgp-tests" version = "0.7.0" dependencies = [ "cgp", - "const_format", + "cgp-macro-test-util", "futures", + "insta", ] [[package]] @@ -231,23 +267,14 @@ dependencies = [ ] [[package]] -name = "const_format" -version = "0.2.35" +name = "console" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "encode_unicode", + "libc", + "windows-sys", ] [[package]] @@ -256,6 +283,22 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "eyre" version = "0.6.12" @@ -266,6 +309,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + [[package]] name = "futures" version = "0.3.31" @@ -355,12 +404,35 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + [[package]] name = "indenter" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" +[[package]] +name = "insta" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82" +dependencies = [ + "console", + "once_cell", + "similar", + "tempfile", +] + [[package]] name = "itertools" version = "0.14.0" @@ -370,6 +442,18 @@ dependencies = [ "either", ] +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + [[package]] name = "memchr" version = "2.7.6" @@ -422,6 +506,31 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "slab" version = "0.4.12" @@ -439,6 +548,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + [[package]] name = "unicode-ident" version = "1.0.22" @@ -446,7 +568,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unicode-xid" -version = "0.2.6" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] diff --git a/Cargo.toml b/Cargo.toml index 15aa0fe3..cf5a47e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ members = [ "crates/macros/cgp-macro", "crates/macros/cgp-macro-core", "crates/macros/cgp-macro-lib", + "crates/macros/cgp-macro-test-util", + "crates/macros/cgp-macro-test-util-lib", "crates/macros/cgp-extra-macro", "crates/macros/cgp-extra-macro-lib", @@ -68,5 +70,7 @@ cgp-async-macro = { version = "0.7.0", path = "./crates/macros/cgp-a cgp-macro = { version = "0.7.0", path = "./crates/macros/cgp-macro" } cgp-macro-core = { version = "0.7.0", path = "./crates/macros/cgp-macro-core" } cgp-macro-lib = { version = "0.7.0", path = "./crates/macros/cgp-macro-lib" } +cgp-macro-test-util = { version = "0.7.0", path = "./crates/macros/cgp-macro-test-util" } +cgp-macro-test-util-lib = { version = "0.7.0", path = "./crates/macros/cgp-macro-test-util-lib" } cgp-extra-macro = { version = "0.7.0", path = "./crates/macros/cgp-extra-macro" } cgp-extra-macro-lib = { version = "0.7.0", path = "./crates/macros/cgp-extra-macro-lib" } diff --git a/crates/macros/cgp-macro-core/Cargo.toml b/crates/macros/cgp-macro-core/Cargo.toml index 2d69a19d..26246f38 100644 --- a/crates/macros/cgp-macro-core/Cargo.toml +++ b/crates/macros/cgp-macro-core/Cargo.toml @@ -7,15 +7,9 @@ repository = { workspace = true } authors = { workspace = true } rust-version = { workspace = true } keywords = { workspace = true } -description = """ - Context-generic programming core component macros implemented as a library. -""" - -[features] -default = [] [dependencies] -syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } -quote = "1.0.38" -proc-macro2 = "1.0.92" -itertools = "0.14.0" +syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } +quote = { version = "1.0.38" } +proc-macro2 = { version = "1.0.92" } +itertools = { version = "0.14.0" } diff --git a/crates/macros/cgp-macro-core/src/functions/mod.rs b/crates/macros/cgp-macro-core/src/functions/mod.rs index 4f687f53..cd188782 100644 --- a/crates/macros/cgp-macro-core/src/functions/mod.rs +++ b/crates/macros/cgp-macro-core/src/functions/mod.rs @@ -7,6 +7,7 @@ mod implicits; mod is_provider_params; mod parse_internal; mod snake_case; +mod strip; pub use camel_case::*; pub use delegated_impls::*; @@ -17,3 +18,4 @@ pub use implicits::*; pub use is_provider_params::*; pub use parse_internal::*; pub use snake_case::*; +pub use strip::*; diff --git a/crates/macros/cgp-macro-core/src/functions/parse_internal.rs b/crates/macros/cgp-macro-core/src/functions/parse_internal.rs index 99f82e9c..1583e161 100644 --- a/crates/macros/cgp-macro-core/src/functions/parse_internal.rs +++ b/crates/macros/cgp-macro-core/src/functions/parse_internal.rs @@ -1,10 +1,11 @@ use core::any::type_name; -use proc_macro2::{Group, TokenStream, TokenTree}; +use proc_macro2::TokenStream; use syn::parse::Parse; use syn::spanned::Spanned; use syn::{Error, parse2}; +use crate::functions::strip_macro_prelude; pub use crate::macros::parse_internal; pub fn parse_internal(body: TokenStream) -> Result @@ -23,57 +24,3 @@ where e }) } - -/// Strips the `::cgp::macro_prelude::` prefix from the [`TokenStream`] so the -/// error message shows the more readable, unqualified paths. The replacement is -/// done at the token level, recursing into nested groups. -fn strip_macro_prelude(body: TokenStream) -> TokenStream { - // The prefix `::cgp::macro_prelude::` is made up of the following tokens. - fn is_prefix(tokens: &[TokenTree]) -> bool { - matches!( - tokens, - [ - TokenTree::Punct(p1), - TokenTree::Punct(p2), - TokenTree::Ident(cgp), - TokenTree::Punct(p3), - TokenTree::Punct(p4), - TokenTree::Ident(prelude), - TokenTree::Punct(p5), - TokenTree::Punct(p6), - ] if p1.as_char() == ':' - && p2.as_char() == ':' - && cgp == "cgp" - && p3.as_char() == ':' - && p4.as_char() == ':' - && prelude == "macro_prelude" - && p5.as_char() == ':' - && p6.as_char() == ':' - ) - } - - const PREFIX_LEN: usize = 8; - - let tokens: Vec = body.into_iter().collect(); - let mut output = Vec::with_capacity(tokens.len()); - let mut i = 0; - - while i < tokens.len() { - if is_prefix(&tokens[i..(i + PREFIX_LEN).min(tokens.len())]) { - i += PREFIX_LEN; - } else { - match &tokens[i] { - TokenTree::Group(group) => { - let inner = strip_macro_prelude(group.stream()); - let mut new_group = Group::new(group.delimiter(), inner); - new_group.set_span(group.span()); - output.push(TokenTree::Group(new_group)); - } - other => output.push(other.clone()), - } - i += 1; - } - } - - output.into_iter().collect() -} diff --git a/crates/macros/cgp-macro-core/src/functions/strip.rs b/crates/macros/cgp-macro-core/src/functions/strip.rs new file mode 100644 index 00000000..dfdea642 --- /dev/null +++ b/crates/macros/cgp-macro-core/src/functions/strip.rs @@ -0,0 +1,55 @@ +use proc_macro2::{Group, TokenStream, TokenTree}; + +/// Strips the `::cgp::macro_prelude::` prefix from the [`TokenStream`] so the +/// error message shows the more readable, unqualified paths. The replacement is +/// done at the token level, recursing into nested groups. +pub fn strip_macro_prelude(body: TokenStream) -> TokenStream { + // The prefix `::cgp::macro_prelude::` is made up of the following tokens. + fn is_prefix(tokens: &[TokenTree]) -> bool { + matches!( + tokens, + [ + TokenTree::Punct(p1), + TokenTree::Punct(p2), + TokenTree::Ident(cgp), + TokenTree::Punct(p3), + TokenTree::Punct(p4), + TokenTree::Ident(prelude), + TokenTree::Punct(p5), + TokenTree::Punct(p6), + ] if p1.as_char() == ':' + && p2.as_char() == ':' + && cgp == "cgp" + && p3.as_char() == ':' + && p4.as_char() == ':' + && prelude == "macro_prelude" + && p5.as_char() == ':' + && p6.as_char() == ':' + ) + } + + const PREFIX_LEN: usize = 8; + + let tokens: Vec = body.into_iter().collect(); + let mut output = Vec::with_capacity(tokens.len()); + let mut i = 0; + + while i < tokens.len() { + if is_prefix(&tokens[i..(i + PREFIX_LEN).min(tokens.len())]) { + i += PREFIX_LEN; + } else { + match &tokens[i] { + TokenTree::Group(group) => { + let inner = strip_macro_prelude(group.stream()); + let mut new_group = Group::new(group.delimiter(), inner); + new_group.set_span(group.span()); + output.push(TokenTree::Group(new_group)); + } + other => output.push(other.clone()), + } + i += 1; + } + } + + output.into_iter().collect() +} diff --git a/crates/macros/cgp-macro-lib/Cargo.toml b/crates/macros/cgp-macro-lib/Cargo.toml index 44e48059..873be4ff 100644 --- a/crates/macros/cgp-macro-lib/Cargo.toml +++ b/crates/macros/cgp-macro-lib/Cargo.toml @@ -7,18 +7,11 @@ repository = { workspace = true } authors = { workspace = true } rust-version = { workspace = true } keywords = { workspace = true } -description = """ - Context-generic programming core component macros implemented as a library. -""" - -[features] -default = [] [dependencies] -cgp-macro-core = { workspace = true } +cgp-macro-core = { workspace = true } syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } -quote = "1.0.38" -proc-macro2 = "1.0.92" -prettyplease = "0.2.27" -itertools = "0.14.0" +quote = { version = "1.0.38" } +proc-macro2 = { version = "1.0.92" } +itertools = { version = "0.14.0" } diff --git a/crates/macros/cgp-macro-test-util-lib/Cargo.toml b/crates/macros/cgp-macro-test-util-lib/Cargo.toml new file mode 100644 index 00000000..0d30a888 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "cgp-macro-test-util-lib" +version = "0.7.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +keywords = { workspace = true } + +[dependencies] +cgp-macro-lib = { workspace = true } +cgp-macro-core = { workspace = true } + +syn = { version = "2.0.95" } +quote = { version = "1.0.38" } +proc-macro2 = { version = "1.0.92" } +prettyplease = { version = "0.2.37" } diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/mod.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/mod.rs new file mode 100644 index 00000000..cca0dee2 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/mod.rs @@ -0,0 +1,25 @@ +mod snapshot_cgp_auto_getter; +mod snapshot_cgp_component; +mod snapshot_cgp_fn; +mod snapshot_cgp_getter; +mod snapshot_cgp_impl; +mod snapshot_cgp_namespace; +mod snapshot_cgp_new_provider; +mod snapshot_cgp_provider; +mod snapshot_cgp_type; +mod snapshot_check_components; +mod snapshot_delegate_and_check_components; +mod snapshot_delegate_components; + +pub use snapshot_cgp_auto_getter::*; +pub use snapshot_cgp_component::*; +pub use snapshot_cgp_fn::*; +pub use snapshot_cgp_getter::*; +pub use snapshot_cgp_impl::*; +pub use snapshot_cgp_namespace::*; +pub use snapshot_cgp_new_provider::*; +pub use snapshot_cgp_provider::*; +pub use snapshot_cgp_type::*; +pub use snapshot_check_components::*; +pub use snapshot_delegate_and_check_components::*; +pub use snapshot_delegate_components::*; diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_auto_getter.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_auto_getter.rs new file mode 100644 index 00000000..0225408c --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_auto_getter.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemTrait, parse2}; + +use crate::keywords::CgpAutoGetter; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_auto_getter(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_auto_getter(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_component.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_component.rs new file mode 100644 index 00000000..36b74092 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_component.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemTrait, parse2}; + +use crate::keywords::CgpComponent; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_component(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_component(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_fn.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_fn.rs new file mode 100644 index 00000000..68fe6002 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_fn.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemFn, parse2}; + +use crate::keywords::CgpFn; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_fn(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_fn(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_getter.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_getter.rs new file mode 100644 index 00000000..bc2a615b --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_getter.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemTrait, parse2}; + +use crate::keywords::CgpGetter; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_getter(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_getter(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_impl.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_impl.rs new file mode 100644 index 00000000..6711cad7 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_impl.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemImpl, parse2}; + +use crate::keywords::CgpImpl; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_impl(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_impl(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_namespace.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_namespace.rs new file mode 100644 index 00000000..82e1870f --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_namespace.rs @@ -0,0 +1,13 @@ +use proc_macro2::TokenStream; +use syn::parse2; + +use crate::keywords::CgpNamespace; +use crate::types::StatementMacroSnapshot; + +pub fn snapshot_cgp_namespace(body: TokenStream) -> syn::Result { + let item: StatementMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_namespace(item.body.clone())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_new_provider.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_new_provider.rs new file mode 100644 index 00000000..2b8e97c0 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_new_provider.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemImpl, parse2}; + +use crate::keywords::CgpNewProvider; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_new_provider(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_new_provider(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_provider.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_provider.rs new file mode 100644 index 00000000..43fc0937 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_provider.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemImpl, parse2}; + +use crate::keywords::CgpProvider; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_provider(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_provider(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_type.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_type.rs new file mode 100644 index 00000000..1f09cecd --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_cgp_type.rs @@ -0,0 +1,14 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{ItemTrait, parse2}; + +use crate::keywords::CgpType; +use crate::types::AttributeMacroSnapshot; + +pub fn snapshot_cgp_type(body: TokenStream) -> syn::Result { + let item: AttributeMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::cgp_type(item.attr, item.body.to_token_stream())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_check_components.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_check_components.rs new file mode 100644 index 00000000..f60047fe --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_check_components.rs @@ -0,0 +1,13 @@ +use proc_macro2::TokenStream; +use syn::parse2; + +use crate::keywords::CheckComponents; +use crate::types::StatementMacroSnapshot; + +pub fn snapshot_check_components(body: TokenStream) -> syn::Result { + let item: StatementMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::check_components(item.body.clone())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_and_check_components.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_and_check_components.rs new file mode 100644 index 00000000..92f2c748 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_and_check_components.rs @@ -0,0 +1,13 @@ +use proc_macro2::TokenStream; +use syn::parse2; + +use crate::keywords::DelegateAndCheckComponents; +use crate::types::StatementMacroSnapshot; + +pub fn snapshot_delegate_and_check_components(body: TokenStream) -> syn::Result { + let item: StatementMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::delegate_and_check_components(item.body.clone())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_components.rs b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_components.rs new file mode 100644 index 00000000..52048f92 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/entrypoints/snapshot_delegate_components.rs @@ -0,0 +1,13 @@ +use proc_macro2::TokenStream; +use syn::parse2; + +use crate::keywords::DelegateComponents; +use crate::types::StatementMacroSnapshot; + +pub fn snapshot_delegate_components(body: TokenStream) -> syn::Result { + let item: StatementMacroSnapshot = parse2(body)?; + + let output = cgp_macro_lib::delegate_components(item.body.clone())?; + + item.snapshot.wrap_output(output) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/functions/mod.rs b/crates/macros/cgp-macro-test-util-lib/src/functions/mod.rs new file mode 100644 index 00000000..586dbf2a --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/functions/mod.rs @@ -0,0 +1,5 @@ +mod parse_attribute; +mod pretty_format; + +pub use parse_attribute::*; +pub use pretty_format::*; diff --git a/crates/macros/cgp-macro-test-util-lib/src/functions/parse_attribute.rs b/crates/macros/cgp-macro-test-util-lib/src/functions/parse_attribute.rs new file mode 100644 index 00000000..85259f88 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/functions/parse_attribute.rs @@ -0,0 +1,27 @@ +use cgp_macro_core::traits::IsKeyword; +use cgp_macro_core::types::keyword::Keyword; +use proc_macro2::TokenStream; +use syn::parse::ParseStream; +use syn::token::Paren; +use syn::{braced, bracketed, parenthesized}; + +pub fn parse_attribute_with_keyword(input: ParseStream) -> syn::Result { + let outer_body; + bracketed!(outer_body in input); + + let _: Keyword = outer_body.parse()?; + + let body = if outer_body.is_empty() { + TokenStream::new() + } else if outer_body.peek(Paren) { + let inner_body; + parenthesized!(inner_body in outer_body); + inner_body.parse()? + } else { + let inner_body; + braced!(inner_body in outer_body); + inner_body.parse()? + }; + + Ok(body) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/functions/pretty_format.rs b/crates/macros/cgp-macro-test-util-lib/src/functions/pretty_format.rs new file mode 100644 index 00000000..034c11d1 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/functions/pretty_format.rs @@ -0,0 +1,10 @@ +use cgp_macro_core::functions::strip_macro_prelude; +use prettyplease::unparse; +use proc_macro2::TokenStream; +use syn::parse2; + +pub fn pretty_format(body: TokenStream) -> syn::Result { + let parsed = parse2(strip_macro_prelude(body))?; + let formatted = unparse(&parsed); + Ok(formatted) +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/keywords.rs b/crates/macros/cgp-macro-test-util-lib/src/keywords.rs new file mode 100644 index 00000000..91c69aaf --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/keywords.rs @@ -0,0 +1,25 @@ +use cgp_macro_core::define_keyword; + +define_keyword!(CgpComponent, "cgp_component"); + +define_keyword!(CgpAutoGetter, "cgp_auto_getter"); + +define_keyword!(CgpGetter, "cgp_getter"); + +define_keyword!(CgpImpl, "cgp_impl"); + +define_keyword!(CgpProvider, "cgp_provider"); + +define_keyword!(CgpNewProvider, "cgp_new_provider"); + +define_keyword!(CgpFn, "cgp_fn"); + +define_keyword!(CgpType, "cgp_type"); + +define_keyword!(CgpNamespace, "cgp_namespace"); + +define_keyword!(DelegateComponents, "delegate_components"); + +define_keyword!(CheckComponents, "check_components"); + +define_keyword!(DelegateAndCheckComponents, "delegate_and_check_components"); diff --git a/crates/macros/cgp-macro-test-util-lib/src/lib.rs b/crates/macros/cgp-macro-test-util-lib/src/lib.rs new file mode 100644 index 00000000..a7817a6a --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/lib.rs @@ -0,0 +1,4 @@ +pub mod entrypoints; +pub mod functions; +pub mod keywords; +pub mod types; diff --git a/crates/macros/cgp-macro-test-util-lib/src/types/attribute_snapshot.rs b/crates/macros/cgp-macro-test-util-lib/src/types/attribute_snapshot.rs new file mode 100644 index 00000000..16e89776 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/types/attribute_snapshot.rs @@ -0,0 +1,35 @@ +use core::marker::PhantomData; + +use cgp_macro_core::traits::IsKeyword; +use proc_macro2::TokenStream; +use syn::parse::{Parse, ParseStream}; +use syn::token::Pound; + +use crate::functions::parse_attribute_with_keyword; +use crate::types::MacroSnapshot; + +pub struct AttributeMacroSnapshot { + pub attr: TokenStream, + pub body: Item, + pub snapshot: MacroSnapshot, + pub phantom: PhantomData, +} + +impl Parse for AttributeMacroSnapshot { + fn parse(input: ParseStream) -> syn::Result { + let _: Pound = input.parse()?; + + let attr = parse_attribute_with_keyword::(input)?; + + let body = input.parse()?; + + let snapshot = input.parse()?; + + Ok(Self { + attr, + body, + snapshot, + phantom: PhantomData, + }) + } +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/types/macro_snapshot.rs b/crates/macros/cgp-macro-test-util-lib/src/types/macro_snapshot.rs new file mode 100644 index 00000000..0981c916 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/types/macro_snapshot.rs @@ -0,0 +1,63 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::parse::{Parse, ParseStream}; +use syn::spanned::Spanned; +use syn::{Ident, LitStr, braced, parenthesized}; + +use crate::functions::pretty_format; + +pub struct MacroSnapshot { + pub test_name: Ident, + pub arg_ident: Ident, + pub expr: TokenStream, +} + +impl MacroSnapshot { + pub fn wrap_output(&self, output: TokenStream) -> syn::Result { + let Self { + test_name, + arg_ident, + expr, + } = self; + + let output_string = pretty_format(output.clone())?; + let output_literal = LitStr::new(&output_string, output.span()); + + let out = quote! { + #output + + #[test] + fn #test_name() { + let #arg_ident = #output_literal; + + #expr + } + }; + + Ok(out) + } +} + +impl Parse for MacroSnapshot { + fn parse(input: ParseStream) -> syn::Result { + let test_name = input.parse()?; + + let arg_ident = { + let arg_body; + parenthesized!(arg_body in input); + arg_body.parse()? + }; + + let expr = { + let expr_body; + braced!(expr_body in input); + expr_body.parse()? + }; + + Ok(MacroSnapshot { + test_name, + arg_ident, + expr, + }) + } +} diff --git a/crates/macros/cgp-macro-test-util-lib/src/types/mod.rs b/crates/macros/cgp-macro-test-util-lib/src/types/mod.rs new file mode 100644 index 00000000..ffef9d53 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/types/mod.rs @@ -0,0 +1,7 @@ +mod attribute_snapshot; +mod macro_snapshot; +mod statement_snapshot; + +pub use attribute_snapshot::*; +pub use macro_snapshot::*; +pub use statement_snapshot::*; diff --git a/crates/macros/cgp-macro-test-util-lib/src/types/statement_snapshot.rs b/crates/macros/cgp-macro-test-util-lib/src/types/statement_snapshot.rs new file mode 100644 index 00000000..7370eca0 --- /dev/null +++ b/crates/macros/cgp-macro-test-util-lib/src/types/statement_snapshot.rs @@ -0,0 +1,36 @@ +use core::marker::PhantomData; + +use cgp_macro_core::traits::IsKeyword; +use cgp_macro_core::types::keyword::Keyword; +use proc_macro2::TokenStream; +use syn::braced; +use syn::parse::{Parse, ParseStream}; +use syn::token::Not; + +use crate::types::MacroSnapshot; + +pub struct StatementMacroSnapshot { + pub body: TokenStream, + pub snapshot: MacroSnapshot, + pub phantom: PhantomData, +} + +impl Parse for StatementMacroSnapshot { + fn parse(input: ParseStream) -> syn::Result { + let _: Keyword = input.parse()?; + let _: Not = input.parse()?; + + let body = { + let body; + braced!(body in input); + body.parse()? + }; + + let snapshot = input.parse()?; + Ok(Self { + body, + snapshot, + phantom: PhantomData, + }) + } +} diff --git a/crates/macros/cgp-macro-test-util/Cargo.toml b/crates/macros/cgp-macro-test-util/Cargo.toml new file mode 100644 index 00000000..53c3b094 --- /dev/null +++ b/crates/macros/cgp-macro-test-util/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "cgp-macro-test-util" +version = "0.7.0" +edition = { workspace = true } +license = { workspace = true } +repository = { workspace = true } +authors = { workspace = true } +rust-version = { workspace = true } +keywords = { workspace = true } + +[lib] +proc-macro = true + +[dependencies] +cgp-macro-lib = { workspace = true } +cgp-macro-core = { workspace = true } +cgp-macro-test-util-lib = { workspace = true } + +syn = { version = "2.0.95", features = [ "full", "extra-traits", "visit", "visit-mut" ] } +quote = { version = "1.0.38" } +proc-macro2 = { version = "1.0.92" } diff --git a/crates/macros/cgp-macro-test-util/README.md b/crates/macros/cgp-macro-test-util/README.md new file mode 100644 index 00000000..800346c4 --- /dev/null +++ b/crates/macros/cgp-macro-test-util/README.md @@ -0,0 +1,454 @@ +# `cgp-macro-test-util` + +Snapshot-testing macros for the CGP procedural macros. + +This crate exposes a family of `snapshot_*!` procedural macros that make it easy +to write **golden / snapshot tests** for the code generated by the core CGP +macros such as `#[cgp_component]`, `#[cgp_impl]`, `#[cgp_auto_getter]`, +`#[cgp_getter]`, `#[cgp_fn]`, and `delegate_components!`. + +The snapshots are asserted using the [`insta`](https://insta.rs) crate. + +## Why snapshot test the macros? + +The CGP macros generate a fair amount of boilerplate: consumer traits, provider +traits, blanket delegation impls, `IsProviderFor` impls, `UseContext` / +`UseField` / `RedirectLookup` providers, and so on. When we change the macro +internals, it is easy to accidentally change the generated output in an +unintended way. + +A snapshot test pins down the *exact* generated code as a human-readable string. +When the generated code changes, the snapshot test fails and shows a diff, +letting us review the change deliberately (and `cargo insta` makes accepting an +intended change a one-liner). + +Crucially, each snapshot macro does **two** things at once: + +1. It **emits the real generated code** into the surrounding module, exactly as + the underlying CGP macro would. The generated traits, structs, and impls are + therefore live and usable by the rest of the module — you can still wire them + up and assert their runtime behavior. +2. It **generates a `#[test]` function** that captures a pretty-printed string of + that same generated code and asserts it against an inline `insta` snapshot. + +Because of (1), migrating an existing test to a snapshot macro does not lose any +compile-time or runtime coverage — it only *adds* a snapshot assertion on top. + +## Crate layout + +This is the proc-macro crate. It is a thin shell: every macro simply forwards to +the implementation crate [`cgp-macro-test-util-lib`](../cgp-macro-test-util-lib), +which is a normal library crate so that the logic can be unit-tested without the +`proc-macro = true` restriction. + +``` +cgp-macro-test-util/ # proc-macro entry points (#[proc_macro] fns) +└── cgp-macro-test-util-lib/ # the actual implementation + ├── entrypoints/ # one function per macro + ├── types/ # parsers (syn `Parse` impls) + MacroSnapshot + └── functions/ # parse_attribute, pretty_format +``` + +The implementation reuses the real macro logic from `cgp-macro-lib` +(`cgp_macro_lib::cgp_component`, `::cgp_impl`, `::cgp_getter`, etc.), so the +snapshot output is guaranteed to match what the production macros generate. + +## Available macros + +| Snapshot macro | Wraps | +| --------------------------- | --------------------- | +| `snapshot_cgp_component!` | `#[cgp_component]` | +| `snapshot_cgp_impl!` | `#[cgp_impl]` | +| `snapshot_cgp_provider!` | `#[cgp_provider]` | +| `snapshot_cgp_new_provider!`| `#[cgp_new_provider]` | +| `snapshot_cgp_auto_getter!` | `#[cgp_auto_getter]` | +| `snapshot_cgp_getter!` | `#[cgp_getter]` | +| `snapshot_cgp_fn!` | `#[cgp_fn]` | +| `snapshot_cgp_type!` | `#[cgp_type]` | +| `snapshot_delegate_components!` | `delegate_components!` | +| `snapshot_check_components!` | `check_components!` | +| `snapshot_delegate_and_check_components!` | `delegate_and_check_components!` | +| `snapshot_cgp_namespace!` | `cgp_namespace!` | + +## Anatomy of a snapshot invocation + +Every snapshot macro takes two parts: + +1. **The item under test**, written *exactly* as you would normally write the + underlying CGP macro invocation (the attribute plus the `trait` / `impl`, or + the full `delegate_components! { ... }` call). +2. **A test block** of the form: + + ```text + () { + > + } + ``` + + - `` becomes the name of the generated `#[test]` function, so it + must be unique within the module. + - `` is the identifier bound to the pretty-printed `&str` of the + generated code inside the test body. It is conventionally named `output`. + - The body is typically a single `insta::assert_snapshot!(, @"...")` + call with an inline snapshot. + +For example: + +```rust +use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_getter; +use insta::assert_snapshot; + +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName { + fn name(&self) -> &str; + } + + expand_has_name(output) { + assert_snapshot!(output, @"...generated code...") + } +} +``` + +This expands to roughly: + +```rust +// (1) the real generated code, identical to what `#[cgp_getter]` produces: +pub trait HasName { /* ... */ } +impl<__Context__> HasName for __Context__ where /* ... */ { /* ... */ } +pub trait NameGetter<__Context__>: /* ... */ { /* ... */ } +pub struct NameGetterComponent; +/* ...UseContext / UseField / UseFields / WithProvider / RedirectLookup impls... */ + +// (2) the generated snapshot test: +#[test] +fn expand_has_name() { + let output = "...pretty-printed generated code..."; + assert_snapshot!(output, @"...generated code..."); +} +``` + +### `snapshot_cgp_component!` + +```rust +snapshot_cgp_component! { + #[cgp_component(Greeter)] + pub trait CanGreet: HasName { + fn greet(&self) -> String; + } + + expand_greeter(output) { + assert_snapshot!(output, @"...") + } +} +``` + +Both the parenthesized form `#[cgp_component(Greeter)]` and the brace form +`#[cgp_component { provider: Greeter, ... }]` are accepted, mirroring the real +macro. + +### `snapshot_cgp_impl!` + +```rust +snapshot_cgp_impl! { + #[cgp_impl(new ValueToString)] + impl FooProvider for Context { + fn foo(&self, value: u32) -> String { + value.to_string() + } + } + + expand_value_to_string(output) { + assert_snapshot!(output, @"...") + } +} +``` + +### `snapshot_cgp_provider!` + +Wraps `#[cgp_provider]` provider impls. The item under test is the full provider +`impl` written exactly as you would normally write it under `#[cgp_provider]` — +the provider struct itself is expected to already be defined elsewhere: + +```rust +pub struct GreetHello; + +snapshot_cgp_provider! { + #[cgp_provider] + impl Greeter for GreetHello + where + Context: HasName, + { + fn greet(context: &Context) { + println!("Hello, {}!", context.name()); + } + } + + expand_greet_hello(output) { + assert_snapshot!(output, @"...") + } +} +``` + +Both the default form `#[cgp_provider]` and the explicit component name form +`#[cgp_provider(GreeterComponent)]` are accepted, mirroring the real macro. In +addition to re-emitting the provider impl, the snapshot captures the generated +`IsProviderFor` impl. + +### `snapshot_cgp_new_provider!` + +Has the identical shape as `snapshot_cgp_provider!`, but wraps +`#[cgp_new_provider]`, which additionally defines the provider struct. The +snapshot therefore also captures the generated `struct` definition: + +```rust +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Greeter for GreetHello + where + Context: HasName, + { + fn greet(context: &Context) { + println!("Hello, {}!", context.name()); + } + } + + expand_greet_hello(output) { + assert_snapshot!(output, @"...") + } +} +``` + +Both the default form `#[cgp_new_provider]` and the explicit component name form +`#[cgp_new_provider(GreeterComponent)]` are accepted, mirroring the real macro. + +### `snapshot_cgp_auto_getter!` / `snapshot_cgp_getter!` + +```rust +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasName { + fn name(&self) -> &str; + } + + expand_has_name(output) { + assert_snapshot!(output, @"...") + } +} +``` + +`snapshot_cgp_getter!` has the identical shape and also accepts the custom +provider name forms `#[cgp_getter(NameGetter)]` and +`#[cgp_getter { provider: ..., name: ... }]`. + +### `snapshot_cgp_fn!` + +The item under test is the full `#[cgp_fn]` function, written exactly as you +would normally write it — including any extra attributes such as `#[uses(...)]`, +`#[extend(...)]`, `#[extend_where(...)]`, `#[use_type(...)]`, `#[impl_generics(...)]`, +or `#[async_trait]`, all kept above the `fn` with `#[cgp_fn]` first: + +```rust +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + assert_snapshot!(output, @"...") + } +} +``` + +Both the default form `#[cgp_fn]` and the custom trait name form +`#[cgp_fn(CanCalculateRectangleArea)]` are accepted, mirroring the real macro. + +### `snapshot_cgp_type!` + +Wraps `#[cgp_type]` abstract-type traits. The item under test is written exactly +as you would normally write the `#[cgp_type]` invocation: + +```rust +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + assert_snapshot!(output, @"...") + } +} +``` + +Both the default form `#[cgp_type]` and the custom provider name forms +`#[cgp_type(ScalarTypeProvider)]` and +`#[cgp_type { provider: ..., derive_delegate: ... }]` are accepted, mirroring the +real macro. In addition to the usual `#[cgp_component]` output, the snapshot +captures the extra `UseType` / `WithProvider` providers that `#[cgp_type]` +generates. + +### `snapshot_delegate_components!` + +Here the *whole* `delegate_components! { ... }` invocation is written verbatim, +followed by the test block: + +```rust +snapshot_delegate_components! { + delegate_components! { + new FooComponents { + Index<0>: u64, + Index<1>: String, + } + } + + expand_foo_components(output) { + assert_snapshot!(output, @"...") + } +} +``` + +### `snapshot_check_components!` + +The *whole* `check_components! { ... }` invocation is written verbatim, followed +by the test block: + +```rust +snapshot_check_components! { + check_components! { + App { + ErrorRaiserComponent: String, + } + } + + expand_check_app(output) { + assert_snapshot!(output, @"...") + } +} +``` + +The body is forwarded to the real macro verbatim, so every `check_components!` +form is accepted — including the `#[check_trait(...)]` and +`#[check_providers(...)]` attributes, `#[check_params(...)]` / generic +parameters, the array syntax for grouping components and params, and multiple +check specs in a single invocation. The snapshot captures the generated check +trait(s) and their `impl` blocks. + +Note that the snapshot macro emits the same check trait/impls into the +surrounding module, so the compile-time wiring check is preserved — it only +*adds* a snapshot assertion on top. + +### `snapshot_delegate_and_check_components!` + +Likewise, the *whole* `delegate_and_check_components! { ... }` invocation is +written verbatim, followed by the test block: + +```rust +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + #[check_trait(CheckMyContext)] + MyContext { + NameTypeProviderComponent: UseType, + NameGetterComponent: UseField, + } + } + + expand_my_context(output) { + assert_snapshot!(output, @"...") + } +} +``` + +All `delegate_and_check_components!` forms are accepted, since the body is +forwarded to the real macro verbatim — including `#[check_trait(...)]`, +`#[check_params(...)]`, `#[skip_check]`, generic parameters, and array syntax. +The snapshot captures both the generated `DelegateComponent` / `IsProviderFor` +impls *and* the generated check trait + impls. + +### `snapshot_cgp_namespace!` + +Like `snapshot_delegate_components!`, the *whole* `cgp_namespace! { ... }` +invocation is written verbatim, followed by the test block: + +```rust +snapshot_cgp_namespace! { + cgp_namespace! { + new MyNamespace { + FooProviderComponent => + @MyApp.MyFooComponent, + } + } + + expand_my_namespace(output) { + assert_snapshot!(output, @"...") + } +} +``` + +All `cgp_namespace!` forms are accepted, since the body is forwarded to the real +macro verbatim — including parent namespaces (`new Extended: DefaultNamespace { ... }`), +symbol/type path keys (`@my_app.MyFooComponent`), and array keys. + +## Workflow with `insta` + +Write the test with an **empty** inline snapshot first: + +```rust +expand_has_name(output) { + assert_snapshot!(output, @"") +} +``` + +Then let `insta` fill it in: + +```bash +# review interactively +cargo insta test -p cgp-tests --test getter +cargo insta review + +# or accept everything non-interactively +cargo insta test -p cgp-tests --accept + +# or via the env var +INSTA_UPDATE=always cargo test -p cgp-tests +``` + +After the first accept, the inline `@"..."` is populated with the pretty-printed +generated code. On subsequent runs the test fails if the generated code changes, +showing a diff you can re-accept once you've confirmed the change is intended. + +## Migrating existing tests + +When migrating an existing macro test, two situations come up: + +- **Module-level macro use** — wrap the existing `#[cgp_component]` / `#[cgp_impl]` + / `#[cgp_getter]` / `#[cgp_auto_getter]` / `delegate_components!` in the matching + `snapshot_*!` macro and append a test block. Nothing else needs to change, + since the snapshot macro re-emits the same code. + +- **CGP components defined *inside* a test function** — the snapshot macro + generates a `#[test]` function, which cannot be nested inside another function. + So the CGP components must be lifted out of the function body: + + - If the test is **purely compile-time** (it only checks that the wiring + compiles, with no runtime assertions), turn the whole test into an inner + `mod` and place the snapshot macro there. + - If the test has **runtime assertions**, create an inner `mod` that holds the + extracted CGP components wrapped in the snapshot macro, and keep the original + `#[test]` function, now referencing the items from the inner module. This + preserves the runtime coverage while adding the snapshot assertion. + +## Notes / limitations + +- Snapshot macros exist only for the macros listed above. Other CGP macros + (`#[cgp_preset]`, …) are not (yet) snapshot-wrapped and are left as-is. +- The pretty-printing is done with + [`prettyplease`](https://crates.io/crates/prettyplease), and any + macro-prelude noise is stripped beforehand + (`cgp_macro_core::functions::strip_macro_prelude`), so the snapshot is stable, + readable Rust source. +- The `` must be unique within its module — when a single file + contains several snapshots, give each a distinct name (e.g. `expand_has_name`, + `expand_greeter`). diff --git a/crates/macros/cgp-macro-test-util/src/lib.rs b/crates/macros/cgp-macro-test-util/src/lib.rs new file mode 100644 index 00000000..0b32b625 --- /dev/null +++ b/crates/macros/cgp-macro-test-util/src/lib.rs @@ -0,0 +1,86 @@ +use cgp_macro_test_util_lib::entrypoints; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn snapshot_delegate_components(body: TokenStream) -> TokenStream { + entrypoints::snapshot_delegate_components(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_component(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_component(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_impl(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_impl(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_provider(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_provider(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_new_provider(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_new_provider(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_fn(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_fn(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_auto_getter(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_auto_getter(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_getter(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_getter(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_namespace(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_namespace(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_cgp_type(body: TokenStream) -> TokenStream { + entrypoints::snapshot_cgp_type(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_check_components(body: TokenStream) -> TokenStream { + entrypoints::snapshot_check_components(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} + +#[proc_macro] +pub fn snapshot_delegate_and_check_components(body: TokenStream) -> TokenStream { + entrypoints::snapshot_delegate_and_check_components(body.into()) + .unwrap_or_else(syn::Error::into_compile_error) + .into() +} diff --git a/crates/macros/cgp-macro/Cargo.toml b/crates/macros/cgp-macro/Cargo.toml index 770dd1fd..e3ea2685 100644 --- a/crates/macros/cgp-macro/Cargo.toml +++ b/crates/macros/cgp-macro/Cargo.toml @@ -7,9 +7,6 @@ repository = { workspace = true } authors = { workspace = true } rust-version = { workspace = true } keywords = { workspace = true } -description = """ - Context-generic programming core component macros -""" [lib] proc-macro = true diff --git a/crates/macros/cgp-macro/src/lib.rs b/crates/macros/cgp-macro/src/lib.rs index acc29b0f..72ad7cfd 100644 --- a/crates/macros/cgp-macro/src/lib.rs +++ b/crates/macros/cgp-macro/src/lib.rs @@ -4,8 +4,6 @@ This crate provides the proc macros used for defining CGP components. */ -extern crate proc_macro; - use proc_macro::TokenStream; /** diff --git a/crates/tests/cgp-tests/Cargo.toml b/crates/tests/cgp-tests/Cargo.toml index 11d13ae4..1575c261 100644 --- a/crates/tests/cgp-tests/Cargo.toml +++ b/crates/tests/cgp-tests/Cargo.toml @@ -7,11 +7,9 @@ repository = { workspace = true } authors = { workspace = true } rust-version = { workspace = true } keywords = { workspace = true } -description = """ - Context-generic programming meta crate -""" [dependencies] -cgp = { workspace = true } -futures = { version = "0.3.31" } -const_format = { version = "0.2.34" } +cgp = { workspace = true } +cgp-macro-test-util = { workspace = true } +insta = { version = "1.48.0" } +futures = { version = "0.3.31" } diff --git a/crates/tests/cgp-tests/src/namespaces/default_impls.rs b/crates/tests/cgp-tests/src/namespaces/default_impls.rs index b72ca309..e6363ea7 100644 --- a/crates/tests/cgp-tests/src/namespaces/default_impls.rs +++ b/crates/tests/cgp-tests/src/namespaces/default_impls.rs @@ -2,47 +2,227 @@ use core::fmt::Display; use cgp::core::component::DefaultImpls1; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_component, snapshot_cgp_impl, snapshot_cgp_namespace}; -#[cgp_component(ShowImpl)] -#[prefix(@test in DefaultNamespace)] -pub trait Show { - fn show(&self, value: &T) -> String; +snapshot_cgp_component! { + #[cgp_component(ShowImpl)] + #[prefix(@test in DefaultNamespace)] + pub trait Show { + fn show(&self, value: &T) -> String; + } + + expand_show(output) { + insta::assert_snapshot!(output, @" + pub trait Show { + fn show(&self, value: &T) -> String; + } + impl<__Context__, T> Show for __Context__ + where + __Context__: ShowImpl<__Context__, T>, + { + fn show(&self, value: &T) -> String { + __Context__::show(self, value) + } + } + pub trait ShowImpl<__Context__, T>: IsProviderFor { + fn show(__context__: &__Context__, value: &T) -> String; + } + impl<__Provider__, __Context__, T> ShowImpl<__Context__, T> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ShowImplComponent, + >>::Delegate: ShowImpl<__Context__, T>, + { + fn show(__context__: &__Context__, value: &T) -> String { + <__Provider__ as DelegateComponent< + ShowImplComponent, + >>::Delegate::show(__context__, value) + } + } + pub struct ShowImplComponent; + impl<__Context__, T> ShowImpl<__Context__, T> for UseContext + where + __Context__: Show, + { + fn show(__context__: &__Context__, value: &T) -> String { + __Context__::show(__context__, value) + } + } + impl<__Context__, T> IsProviderFor for UseContext + where + __Context__: Show, + {} + impl<__Context__, T, __Components__, __Path__> ShowImpl<__Context__, T> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: ShowImpl<__Context__, T>, + { + fn show(__context__: &__Context__, value: &T) -> String { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::show(__context__, value) + } + } + impl< + __Context__, + T, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + ShowImpl<__Context__, T>, + {} + impl<__Components__> DefaultNamespace<__Components__> for ShowImplComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons, + >, + >; + } + ") + } } -#[cgp_impl(new ShowString)] -#[default_impl(String in DefaultImpls1)] -impl ShowImpl { - fn show(&self, value: &String) -> String { - value.clone() +snapshot_cgp_impl! { + #[cgp_impl(new ShowString)] + #[default_impl(String in DefaultImpls1)] + impl ShowImpl { + fn show(&self, value: &String) -> String { + value.clone() + } + } + + expand_show_string(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> ShowImpl<__Context__, String> for ShowString { + fn show(__context__: &__Context__, value: &String) -> String { + value.clone() + } + } + impl<__Context__> IsProviderFor + for ShowString {} + pub struct ShowString; + impl<__Components__> DefaultImpls1 for String { + type Delegate = ShowString; + } + ") } } -#[cgp_impl(new ShowWithDisplay)] -impl ShowImpl { - fn show(&self, value: &T) -> String { - value.to_string() +snapshot_cgp_impl! { + #[cgp_impl(new ShowWithDisplay)] + impl ShowImpl { + fn show(&self, value: &T) -> String { + value.to_string() + } + } + + expand_show_with_display(output) { + insta::assert_snapshot!(output, @" + impl<__Context__, T: Display> ShowImpl<__Context__, T> for ShowWithDisplay { + fn show(__context__: &__Context__, value: &T) -> String { + value.to_string() + } + } + impl<__Context__, T: Display> IsProviderFor + for ShowWithDisplay {} + pub struct ShowWithDisplay; + ") } } -cgp_namespace! { - new DefaultShowComponents { - [ - String, - u64, - ]: - ShowWithDisplay, +snapshot_cgp_namespace! { + cgp_namespace! { + new DefaultShowComponents { + [ + String, + u64, + ]: + ShowWithDisplay, + } + } + + expand_default_show_components(output) { + insta::assert_snapshot!(output, @" + pub trait DefaultShowComponents<__Table__> { + type Delegate; + } + impl<__Table__> DefaultShowComponents<__Table__> for String { + type Delegate = ShowWithDisplay; + } + impl<__Table__> DefaultShowComponents<__Table__> for u64 { + type Delegate = ShowWithDisplay; + } + ") } } -cgp_namespace! { - new ExtendedNamespace: DefaultNamespace { +snapshot_cgp_namespace! { + cgp_namespace! { + new ExtendedNamespace: DefaultNamespace { + } + } + + expand_default_impls_extended_namespace(output) { + insta::assert_snapshot!(output, @" + pub struct __ExtendedNamespaceComponents; + pub trait ExtendedNamespace<__Table__> { + type Delegate; + } + impl<__Table__, __Key__, __Value__> ExtendedNamespace<__Table__> for __Key__ + where + __Key__: DefaultNamespace<__ExtendedNamespaceComponents>, + __Key__: DefaultNamespace<__Table__, Delegate = __Value__>, + { + type Delegate = __Value__; + } + ") } } -#[cgp_impl(new ShowU32)] -#[default_impl(@test.ShowImplComponent.u32 in ExtendedNamespace)] -impl ShowImpl { - fn show(&self, value: &u32) -> String { - value.to_string() +snapshot_cgp_impl! { + #[cgp_impl(new ShowU32)] + #[default_impl(@test.ShowImplComponent.u32 in ExtendedNamespace)] + impl ShowImpl { + fn show(&self, value: &u32) -> String { + value.to_string() + } + } + + expand_show_u32(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> ShowImpl<__Context__, u32> for ShowU32 { + fn show(__context__: &__Context__, value: &u32) -> String { + value.to_string() + } + } + impl<__Context__> IsProviderFor for ShowU32 {} + pub struct ShowU32; + impl<__Components__> ExtendedNamespace<__Components__> + for PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + > { + type Delegate = ShowU32; + } + ") } } diff --git a/crates/tests/cgp-tests/src/namespaces/extended.rs b/crates/tests/cgp-tests/src/namespaces/extended.rs index 2e74b25e..a87df68c 100644 --- a/crates/tests/cgp-tests/src/namespaces/extended.rs +++ b/crates/tests/cgp-tests/src/namespaces/extended.rs @@ -1,8 +1,43 @@ -use cgp::prelude::{DefaultNamespace, cgp_namespace}; +use cgp::prelude::DefaultNamespace; +use cgp_macro_test_util::snapshot_cgp_namespace; -cgp_namespace! { - new ExtendedNamespace: DefaultNamespace { - @cgp.core.error => - @app, +snapshot_cgp_namespace! { + cgp_namespace! { + new ExtendedNamespace: DefaultNamespace { + @cgp.core.error => + @app, + } + } + + expand_extended_namespace(output) { + insta::assert_snapshot!(output, @" + pub struct __ExtendedNamespaceComponents; + pub trait ExtendedNamespace<__Table__> { + type Delegate; + } + impl<__Table__, __Key__, __Value__> ExtendedNamespace<__Table__> for __Key__ + where + __Key__: DefaultNamespace<__ExtendedNamespaceComponents>, + __Key__: DefaultNamespace<__Table__, Delegate = __Value__>, + { + type Delegate = __Value__; + } + impl<__Table__, __Wildcard__> ExtendedNamespace<__Table__> + for PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol<5, Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>>, + __Wildcard__, + >, + >, + > { + type Delegate = RedirectLookup< + __Table__, + PathCons>>>, __Wildcard__>, + >; + } + ") } } diff --git a/crates/tests/cgp-tests/src/tests/async/spawn.rs b/crates/tests/cgp-tests/src/tests/async/spawn.rs index d36c3adb..5490700f 100644 --- a/crates/tests/cgp-tests/src/tests/async/spawn.rs +++ b/crates/tests/cgp-tests/src/tests/async/spawn.rs @@ -17,6 +17,10 @@ use cgp::extra::run::{ CanRun, CanSendRun, Runner, RunnerComponent, SendRunner, SendRunnerComponent, }; use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_new_provider, snapshot_cgp_provider, snapshot_cgp_type, + snapshot_delegate_components, +}; use futures::executor::block_on; // A dummy spawn function that has the same signature as tokio::spawn, @@ -30,98 +34,718 @@ where // The abstract types and interfaces do not contain explicit Send bounds -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_component(FooFetcher)] -#[async_trait] -pub trait CanFetchFoo: HasFooType + HasErrorType { - async fn fetch_foo(&self) -> Result; +snapshot_cgp_component! { + #[cgp_component(FooFetcher)] + #[async_trait] + pub trait CanFetchFoo: HasFooType + HasErrorType { + async fn fetch_foo(&self) -> Result; + } + + expand_can_fetch_foo(output) { + insta::assert_snapshot!(output, @" + #[async_trait] + pub trait CanFetchFoo: HasFooType + HasErrorType { + async fn fetch_foo(&self) -> Result; + } + #[async_trait] + impl<__Context__> CanFetchFoo for __Context__ + where + __Context__: HasFooType + HasErrorType, + __Context__: FooFetcher<__Context__>, + { + async fn fetch_foo(&self) -> Result { + __Context__::fetch_foo(self).await + } + } + #[async_trait] + pub trait FooFetcher<__Context__>: IsProviderFor + where + __Context__: HasFooType + HasErrorType, + { + async fn fetch_foo( + __context__: &__Context__, + ) -> Result<__Context__::Foo, __Context__::Error>; + } + #[async_trait] + impl<__Provider__, __Context__> FooFetcher<__Context__> for __Provider__ + where + __Context__: HasFooType + HasErrorType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooFetcherComponent, + >>::Delegate: FooFetcher<__Context__>, + { + async fn fetch_foo( + __context__: &__Context__, + ) -> Result<__Context__::Foo, __Context__::Error> { + <__Provider__ as DelegateComponent< + FooFetcherComponent, + >>::Delegate::fetch_foo(__context__) + .await + } + } + pub struct FooFetcherComponent; + #[async_trait] + impl<__Context__> FooFetcher<__Context__> for UseContext + where + __Context__: HasFooType + HasErrorType, + __Context__: CanFetchFoo, + { + async fn fetch_foo( + __context__: &__Context__, + ) -> Result<__Context__::Foo, __Context__::Error> { + __Context__::fetch_foo(__context__).await + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType + HasErrorType, + __Context__: CanFetchFoo, + {} + #[async_trait] + impl<__Context__, __Components__, __Path__> FooFetcher<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooFetcher<__Context__>, + { + async fn fetch_foo( + __context__: &__Context__, + ) -> Result<__Context__::Foo, __Context__::Error> { + <__Components__ as DelegateComponent<__Path__>>::Delegate::fetch_foo(__context__) + .await + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooFetcher<__Context__>, + {} + ") + } } -#[cgp_component(BarFetcher)] -#[async_trait] -pub trait CanFetchBar: HasBarType + HasErrorType { - async fn fetch_bar(&self) -> Result; +snapshot_cgp_component! { + #[cgp_component(BarFetcher)] + #[async_trait] + pub trait CanFetchBar: HasBarType + HasErrorType { + async fn fetch_bar(&self) -> Result; + } + + expand_can_fetch_bar(output) { + insta::assert_snapshot!(output, @" + #[async_trait] + pub trait CanFetchBar: HasBarType + HasErrorType { + async fn fetch_bar(&self) -> Result; + } + #[async_trait] + impl<__Context__> CanFetchBar for __Context__ + where + __Context__: HasBarType + HasErrorType, + __Context__: BarFetcher<__Context__>, + { + async fn fetch_bar(&self) -> Result { + __Context__::fetch_bar(self).await + } + } + #[async_trait] + pub trait BarFetcher<__Context__>: IsProviderFor + where + __Context__: HasBarType + HasErrorType, + { + async fn fetch_bar( + __context__: &__Context__, + ) -> Result<__Context__::Bar, __Context__::Error>; + } + #[async_trait] + impl<__Provider__, __Context__> BarFetcher<__Context__> for __Provider__ + where + __Context__: HasBarType + HasErrorType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarFetcherComponent, + >>::Delegate: BarFetcher<__Context__>, + { + async fn fetch_bar( + __context__: &__Context__, + ) -> Result<__Context__::Bar, __Context__::Error> { + <__Provider__ as DelegateComponent< + BarFetcherComponent, + >>::Delegate::fetch_bar(__context__) + .await + } + } + pub struct BarFetcherComponent; + #[async_trait] + impl<__Context__> BarFetcher<__Context__> for UseContext + where + __Context__: HasBarType + HasErrorType, + __Context__: CanFetchBar, + { + async fn fetch_bar( + __context__: &__Context__, + ) -> Result<__Context__::Bar, __Context__::Error> { + __Context__::fetch_bar(__context__).await + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType + HasErrorType, + __Context__: CanFetchBar, + {} + #[async_trait] + impl<__Context__, __Components__, __Path__> BarFetcher<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarFetcher<__Context__>, + { + async fn fetch_bar( + __context__: &__Context__, + ) -> Result<__Context__::Bar, __Context__::Error> { + <__Components__ as DelegateComponent<__Path__>>::Delegate::fetch_bar(__context__) + .await + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarFetcher<__Context__>, + {} + ") + } } -#[cgp_component(FooBarRunner)] -#[async_trait] -pub trait CanRunFooBar: HasFooType + HasBarType + HasErrorType { - async fn run_foo_bar(&self, foo: &Self::Foo, bar: &Self::Bar) -> Result<(), Self::Error>; +snapshot_cgp_component! { + #[cgp_component(FooBarRunner)] + #[async_trait] + pub trait CanRunFooBar: HasFooType + HasBarType + HasErrorType { + async fn run_foo_bar(&self, foo: &Self::Foo, bar: &Self::Bar) -> Result<(), Self::Error>; + } + + expand_can_run_foo_bar(output) { + insta::assert_snapshot!(output, @" + #[async_trait] + pub trait CanRunFooBar: HasFooType + HasBarType + HasErrorType { + async fn run_foo_bar( + &self, + foo: &Self::Foo, + bar: &Self::Bar, + ) -> Result<(), Self::Error>; + } + #[async_trait] + impl<__Context__> CanRunFooBar for __Context__ + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Context__: FooBarRunner<__Context__>, + { + async fn run_foo_bar( + &self, + foo: &Self::Foo, + bar: &Self::Bar, + ) -> Result<(), Self::Error> { + __Context__::run_foo_bar(self, foo, bar).await + } + } + #[async_trait] + pub trait FooBarRunner< + __Context__, + >: IsProviderFor + where + __Context__: HasFooType + HasBarType + HasErrorType, + { + async fn run_foo_bar( + __context__: &__Context__, + foo: &__Context__::Foo, + bar: &__Context__::Bar, + ) -> Result<(), __Context__::Error>; + } + #[async_trait] + impl<__Provider__, __Context__> FooBarRunner<__Context__> for __Provider__ + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooBarRunnerComponent, + >>::Delegate: FooBarRunner<__Context__>, + { + async fn run_foo_bar( + __context__: &__Context__, + foo: &__Context__::Foo, + bar: &__Context__::Bar, + ) -> Result<(), __Context__::Error> { + <__Provider__ as DelegateComponent< + FooBarRunnerComponent, + >>::Delegate::run_foo_bar(__context__, foo, bar) + .await + } + } + pub struct FooBarRunnerComponent; + #[async_trait] + impl<__Context__> FooBarRunner<__Context__> for UseContext + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Context__: CanRunFooBar, + { + async fn run_foo_bar( + __context__: &__Context__, + foo: &__Context__::Foo, + bar: &__Context__::Bar, + ) -> Result<(), __Context__::Error> { + __Context__::run_foo_bar(__context__, foo, bar).await + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Context__: CanRunFooBar, + {} + #[async_trait] + impl<__Context__, __Components__, __Path__> FooBarRunner<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooBarRunner<__Context__>, + { + async fn run_foo_bar( + __context__: &__Context__, + foo: &__Context__::Foo, + bar: &__Context__::Bar, + ) -> Result<(), __Context__::Error> { + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate::run_foo_bar(__context__, foo, bar) + .await + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasBarType + HasErrorType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooBarRunner<__Context__>, + {} + ") + } } // Abstract providers can be implemented without Send bounds -#[cgp_new_provider(RunnerComponent)] -impl Runner for RunWithFooBar -where - Context: CanFetchFoo + CanFetchBar + CanRunFooBar, -{ - async fn run(context: &Context, _code: PhantomData) -> Result<(), Context::Error> { - let foo = context.fetch_foo().await?; - let bar = context.fetch_bar().await?; +snapshot_cgp_new_provider! { + #[cgp_new_provider(RunnerComponent)] + impl Runner for RunWithFooBar + where + Context: CanFetchFoo + CanFetchBar + CanRunFooBar, + { + async fn run(context: &Context, _code: PhantomData) -> Result<(), Context::Error> { + let foo = context.fetch_foo().await?; + let bar = context.fetch_bar().await?; - context.run_foo_bar(&foo, &bar).await?; + context.run_foo_bar(&foo, &bar).await?; + + Ok(()) + } + } - Ok(()) + expand_run_with_foo_bar(output) { + insta::assert_snapshot!(output, @" + impl Runner for RunWithFooBar + where + Context: CanFetchFoo + CanFetchBar + CanRunFooBar, + { + async fn run( + context: &Context, + _code: PhantomData, + ) -> Result<(), Context::Error> { + let foo = context.fetch_foo().await?; + let bar = context.fetch_bar().await?; + context.run_foo_bar(&foo, &bar).await?; + Ok(()) + } + } + impl IsProviderFor for RunWithFooBar + where + Context: CanFetchFoo + CanFetchBar + CanRunFooBar, + {} + pub struct RunWithFooBar; + ") } } -#[cgp_new_provider(RunnerComponent)] -impl Runner for SpawnAndRun -where - Context: 'static + Send + Clone + CanSendRun, -{ - async fn run(context: &Context, _code: PhantomData) -> Result<(), Context::Error> { - let context = context.clone(); +snapshot_cgp_new_provider! { + #[cgp_new_provider(RunnerComponent)] + impl Runner for SpawnAndRun + where + Context: 'static + Send + Clone + CanSendRun, + { + async fn run(context: &Context, _code: PhantomData) -> Result<(), Context::Error> { + let context = context.clone(); - dummy_spawn(async move { - let _ = context.send_run(PhantomData).await; - }); + dummy_spawn(async move { + let _ = context.send_run(PhantomData).await; + }); - Ok(()) + Ok(()) + } + } + + expand_spawn_and_run(output) { + insta::assert_snapshot!(output, @" + impl Runner for SpawnAndRun + where + Context: 'static + Send + Clone + CanSendRun, + { + async fn run( + context: &Context, + _code: PhantomData, + ) -> Result<(), Context::Error> { + let context = context.clone(); + dummy_spawn(async move { + let _ = context.send_run(PhantomData).await; + }); + Ok(()) + } + } + impl IsProviderFor + for SpawnAndRun + where + Context: 'static + Send + Clone + CanSendRun, + {} + pub struct SpawnAndRun(pub ::core::marker::PhantomData<(InCode)>); + ") } } -#[cgp_new_provider] -impl FooFetcher for DummyFetchFoo -where - Context: HasFooType + HasErrorType, -{ - async fn fetch_foo(_context: &Context) -> Result { - Ok(Default::default()) +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl FooFetcher for DummyFetchFoo + where + Context: HasFooType + HasErrorType, + { + async fn fetch_foo(_context: &Context) -> Result { + Ok(Default::default()) + } + } + + expand_dummy_fetch_foo(output) { + insta::assert_snapshot!(output, @" + impl FooFetcher for DummyFetchFoo + where + Context: HasFooType + HasErrorType, + { + async fn fetch_foo(_context: &Context) -> Result { + Ok(Default::default()) + } + } + impl IsProviderFor for DummyFetchFoo + where + Context: HasFooType + HasErrorType, + {} + pub struct DummyFetchFoo; + ") } } -#[cgp_new_provider] -impl BarFetcher for DummyFetchBar -where - Context: HasBarType + HasErrorType, -{ - async fn fetch_bar(_context: &Context) -> Result { - Ok(Default::default()) +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl BarFetcher for DummyFetchBar + where + Context: HasBarType + HasErrorType, + { + async fn fetch_bar(_context: &Context) -> Result { + Ok(Default::default()) + } + } + + expand_dummy_fetch_bar(output) { + insta::assert_snapshot!(output, @" + impl BarFetcher for DummyFetchBar + where + Context: HasBarType + HasErrorType, + { + async fn fetch_bar(_context: &Context) -> Result { + Ok(Default::default()) + } + } + impl IsProviderFor for DummyFetchBar + where + Context: HasBarType + HasErrorType, + {} + pub struct DummyFetchBar; + ") } } -#[cgp_new_provider] -impl FooBarRunner for DummyRunFoobar -where - Context: HasFooType + HasBarType + HasErrorType, -{ - async fn run_foo_bar( - _context: &Context, - _foo: &Context::Foo, - _bar: &Context::Bar, - ) -> Result<(), Context::Error> { - Ok(()) +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl FooBarRunner for DummyRunFoobar + where + Context: HasFooType + HasBarType + HasErrorType, + { + async fn run_foo_bar( + _context: &Context, + _foo: &Context::Foo, + _bar: &Context::Bar, + ) -> Result<(), Context::Error> { + Ok(()) + } + } + + expand_dummy_run_foo_bar(output) { + insta::assert_snapshot!(output, @" + impl FooBarRunner for DummyRunFoobar + where + Context: HasFooType + HasBarType + HasErrorType, + { + async fn run_foo_bar( + _context: &Context, + _foo: &Context::Foo, + _bar: &Context::Bar, + ) -> Result<(), Context::Error> { + Ok(()) + } + } + impl IsProviderFor for DummyRunFoobar + where + Context: HasFooType + HasBarType + HasErrorType, + {} + pub struct DummyRunFoobar; + ") } } @@ -133,26 +757,118 @@ pub struct App; pub struct ActionA; pub struct ActionB; -delegate_components! { - App { - ErrorTypeProviderComponent: - UseType, - [ - FooTypeProviderComponent, - BarTypeProviderComponent, - ]: - UseType<()>, - FooFetcherComponent: - DummyFetchFoo, - BarFetcherComponent: - DummyFetchBar, - FooBarRunnerComponent: - DummyRunFoobar, - RunnerComponent: - UseDelegate, - }>, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: + UseType, + [ + FooTypeProviderComponent, + BarTypeProviderComponent, + ]: + UseType<()>, + FooFetcherComponent: + DummyFetchFoo, + BarFetcherComponent: + DummyFetchBar, + FooBarRunnerComponent: + DummyRunFoobar, + RunnerComponent: + UseDelegate, + }>, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + pub struct AppRunnerComponents; + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType< + Infallible, + >: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = DummyFetchFoo; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + DummyFetchFoo: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = DummyFetchBar; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + DummyFetchBar: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = DummyRunFoobar; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + DummyRunFoobar: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseDelegate; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseDelegate< + AppRunnerComponents, + >: IsProviderFor, + {} + impl DelegateComponent for AppRunnerComponents { + type Delegate = RunWithFooBar; + } + impl<__Context__, __Params__> IsProviderFor + for AppRunnerComponents + where + RunWithFooBar: IsProviderFor, + {} + impl DelegateComponent for AppRunnerComponents { + type Delegate = SpawnAndRun; + } + impl<__Context__, __Params__> IsProviderFor + for AppRunnerComponents + where + SpawnAndRun: IsProviderFor, + {} + ") } } @@ -160,10 +876,26 @@ delegate_components! { // call to Runner that is implemented by `RunWithFooBar`. // With the concrete context known, the Send bound can be found in the concrete future. -#[cgp_provider] -impl SendRunner for App { - async fn send_run(context: &App, code: PhantomData) -> Result<(), Infallible> { - context.run(code).await +snapshot_cgp_provider! { + #[cgp_provider] + impl SendRunner for App { + async fn send_run(context: &App, code: PhantomData) -> Result<(), Infallible> { + context.run(code).await + } + } + + expand_app_send_runner(output) { + insta::assert_snapshot!(output, @" + impl SendRunner for App { + async fn send_run( + context: &App, + code: PhantomData, + ) -> Result<(), Infallible> { + context.run(code).await + } + } + impl IsProviderFor for App {} + ") } } diff --git a/crates/tests/cgp-tests/src/tests/check_components.rs b/crates/tests/cgp-tests/src/tests/check_components.rs index f32036d1..5daf1824 100644 --- a/crates/tests/cgp-tests/src/tests/check_components.rs +++ b/crates/tests/cgp-tests/src/tests/check_components.rs @@ -1,33 +1,569 @@ #![allow(dead_code)] -use core::marker::PhantomData; +mod basic_check_components { + use core::marker::PhantomData; -use cgp::prelude::*; + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_getter, snapshot_cgp_type, snapshot_check_components, + snapshot_delegate_and_check_components, + }; -#[test] -pub fn test_basic_check_components() { - #[cgp_type] - pub trait HasFooType { - type Foo; + snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } - #[cgp_type] - pub trait HasBarType { - type Bar; + snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } - #[cgp_getter { - provider: FooGetterAt, - }] - pub trait HasFooAt: HasFooType { - fn foo(&self, _tag: PhantomData) -> &Self::Foo; + snapshot_cgp_getter! { + #[cgp_getter { + provider: FooGetterAt, + }] + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + + expand_has_foo_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + impl<__Context__, I> HasFooAt for __Context__ + where + __Context__: HasFooType, + __Context__: FooGetterAt<__Context__, I>, + { + fn foo(&self, _tag: PhantomData) -> &Self::Foo { + __Context__::foo(self, _tag) + } + } + pub trait FooGetterAt< + __Context__, + I, + >: IsProviderFor + where + __Context__: HasFooType, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo; + } + impl<__Provider__, __Context__, I> FooGetterAt<__Context__, I> for __Provider__ + where + __Context__: HasFooType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate: FooGetterAt<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct FooGetterAtComponent; + impl<__Context__, I> FooGetterAt<__Context__, I> for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + __Context__::foo(__context__, _tag) + } + } + impl<__Context__, I> IsProviderFor for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + {} + impl<__Context__, I, __Components__, __Path__> FooGetterAt<__Context__, I> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: FooGetterAt<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + FooGetterAt<__Context__, I>, + {} + impl<__Context__, I> FooGetterAt<__Context__, I> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__, I> IsProviderFor for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + {} + impl<__Context__, I, __Tag__> FooGetterAt<__Context__, I> for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, I, __Provider__> FooGetterAt<__Context__, I> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, I, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + {} + ") + } } - #[cgp_getter { - provider: BarGetterAt, - }] - pub trait HasBarAt: HasBarType { - fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + snapshot_cgp_getter! { + #[cgp_getter { + provider: BarGetterAt, + }] + pub trait HasBarAt: HasBarType { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + } + + expand_has_bar_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarAt: HasBarType { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + } + impl<__Context__, I, J> HasBarAt for __Context__ + where + __Context__: HasBarType, + __Context__: BarGetterAt<__Context__, I, J>, + { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar { + __Context__::foo(self, _tag) + } + } + pub trait BarGetterAt< + __Context__, + I, + J, + >: IsProviderFor + where + __Context__: HasBarType, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar; + } + impl<__Provider__, __Context__, I, J> BarGetterAt<__Context__, I, J> for __Provider__ + where + __Context__: HasBarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarGetterAtComponent, + >>::Delegate: BarGetterAt<__Context__, I, J>, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + BarGetterAtComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct BarGetterAtComponent; + impl<__Context__, I, J> BarGetterAt<__Context__, I, J> for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + __Context__::foo(__context__, _tag) + } + } + impl<__Context__, I, J> IsProviderFor + for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + {} + impl<__Context__, I, J, __Components__, __Path__> BarGetterAt<__Context__, I, J> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: BarGetterAt<__Context__, I, J>, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I, + J, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: IsProviderFor + + BarGetterAt<__Context__, I, J>, + {} + impl<__Context__, I, J> BarGetterAt<__Context__, I, J> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Bar, + >, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__, I, J> IsProviderFor + for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Bar, + >, + {} + impl<__Context__, I, J, __Tag__> BarGetterAt<__Context__, I, J> for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, J, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, I, J, __Provider__> BarGetterAt<__Context__, I, J> + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterAtComponent, + Value = __Context__::Bar, + >, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl< + __Context__, + I, + J, + __Provider__, + > IsProviderFor for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterAtComponent, + Value = __Context__::Bar, + >, + {} + ") + } } #[derive(HasField)] @@ -36,119 +572,813 @@ pub fn test_basic_check_components() { pub extra_dummy: (), } - delegate_and_check_components! { - Context { - [ - FooTypeProviderComponent, - BarTypeProviderComponent, - ]: - UseType<()>, + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Context { + [ + FooTypeProviderComponent, + BarTypeProviderComponent, + ]: + UseType<()>, - #[check_params( - (Index<5>, Index<6>), - (Index<7>, Index<8>), - )] - [ #[check_params( + (Index<5>, Index<6>), + (Index<7>, Index<8>), + )] + [ + #[check_params( + Index<0>, + Index<1>, + )] + FooGetterAtComponent, + + #[check_params( + (Index<0>, Index<1>), + (Index<1>, Index<0>), + )] + BarGetterAtComponent, + ]: + UseField, + } + } + + expand_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for Context { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for Context { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for Context { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseField< + Symbol!("dummy"), + >: IsProviderFor, + {} + impl DelegateComponent for Context { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseField< + Symbol!("dummy"), + >: IsProviderFor, + {} + trait __CanUseContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseContext for Context {} + impl __CanUseContext for Context {} + impl __CanUseContext> for Context {} + impl __CanUseContext> for Context {} + impl __CanUseContext, Index<6>)> for Context {} + impl __CanUseContext, Index<8>)> for Context {} + impl __CanUseContext, Index<1>)> for Context {} + impl __CanUseContext, Index<0>)> for Context {} + impl __CanUseContext, Index<6>)> for Context {} + impl __CanUseContext, Index<8>)> for Context {} + "#) + } + } + + snapshot_check_components! { + check_components! { + #[check_trait(CanUseContext)] + Context { + FooTypeProviderComponent, + BarTypeProviderComponent, + FooGetterAtComponent: [ Index<0>, Index<1>, - )] - FooGetterAtComponent, + ], + FooGetterAtComponent: + Index<3>, + } - #[check_params( + #[check_trait(CanUseContext2)] + Context { + BarGetterAtComponent: [ (Index<0>, Index<1>), (Index<1>, Index<0>), - )] - BarGetterAtComponent, - ]: + ], + BarGetterAtComponent: + (Index<3>, Index<4>), + [ + FooGetterAtComponent, + BarGetterAtComponent, + ]: [ + (Index<5>, Index<6>), + (Index<7>, Index<8>), + ] + } + + #[check_trait(CanUseDummyField)] + #[check_providers( UseField, + UseField, + )] + Context { + FooGetterAtComponent: [ + Index<0>, + Index<1>, + ], + FooGetterAtComponent: + Index<3>, + BarGetterAtComponent: [ + (Index<0>, Index<1>), + (Index<1>, Index<0>), + ], + BarGetterAtComponent: + (Index<3>, Index<4>), + [ + FooGetterAtComponent, + BarGetterAtComponent, + ]: [ + (Index<5>, Index<6>), + (Index<7>, Index<8>), + ] + } } - } - check_components! { - #[check_trait(CanUseContext)] - Context { - FooTypeProviderComponent, - BarTypeProviderComponent, - FooGetterAtComponent: [ - Index<0>, - Index<1>, - ], - FooGetterAtComponent: - Index<3>, - } - - #[check_trait(CanUseContext2)] - Context { - BarGetterAtComponent: [ - (Index<0>, Index<1>), - (Index<1>, Index<0>), - ], - BarGetterAtComponent: - (Index<3>, Index<4>), - [ - FooGetterAtComponent, - BarGetterAtComponent, - ]: [ - (Index<5>, Index<6>), - (Index<7>, Index<8>), - ] - } - - #[check_trait(CanUseDummyField)] - #[check_providers( - UseField, - UseField, - )] - Context { - FooGetterAtComponent: [ - Index<0>, - Index<1>, - ], - FooGetterAtComponent: - Index<3>, - BarGetterAtComponent: [ - (Index<0>, Index<1>), - (Index<1>, Index<0>), - ], - BarGetterAtComponent: - (Index<3>, Index<4>), - [ - FooGetterAtComponent, - BarGetterAtComponent, - ]: [ - (Index<5>, Index<6>), - (Index<7>, Index<8>), - ] + expand_check_context(output) { + insta::assert_snapshot!(output, @r#" + trait CanUseContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseContext for Context {} + impl CanUseContext for Context {} + impl CanUseContext> for Context {} + impl CanUseContext> for Context {} + impl CanUseContext> for Context {} + trait CanUseContext2< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseContext2, Index<1>)> for Context {} + impl CanUseContext2, Index<0>)> for Context {} + impl CanUseContext2, Index<4>)> for Context {} + impl CanUseContext2, Index<6>)> for Context {} + impl CanUseContext2, Index<8>)> for Context {} + impl CanUseContext2, Index<6>)> for Context {} + impl CanUseContext2, Index<8>)> for Context {} + trait CanUseDummyField< + __Component__, + __Params__: ?Sized, + >: IsProviderFor<__Component__, Context, __Params__> {} + impl CanUseDummyField> for UseField {} + impl CanUseDummyField> + for UseField {} + impl CanUseDummyField> for UseField {} + impl CanUseDummyField> + for UseField {} + impl CanUseDummyField> for UseField {} + impl CanUseDummyField> + for UseField {} + impl CanUseDummyField, Index<1>)> + for UseField {} + impl CanUseDummyField, Index<1>)> + for UseField {} + impl CanUseDummyField, Index<0>)> + for UseField {} + impl CanUseDummyField, Index<0>)> + for UseField {} + impl CanUseDummyField, Index<4>)> + for UseField {} + impl CanUseDummyField, Index<4>)> + for UseField {} + impl CanUseDummyField, Index<6>)> + for UseField {} + impl CanUseDummyField, Index<6>)> + for UseField {} + impl CanUseDummyField, Index<8>)> + for UseField {} + impl CanUseDummyField, Index<8>)> + for UseField {} + impl CanUseDummyField, Index<6>)> + for UseField {} + impl CanUseDummyField, Index<6>)> + for UseField {} + impl CanUseDummyField, Index<8>)> + for UseField {} + impl CanUseDummyField, Index<8>)> + for UseField {} + "#) } } } -#[test] -pub fn test_generic_check_components() { - #[cgp_type] - pub trait HasFooType { - type Foo; +mod generic_check_components { + use core::marker::PhantomData; + + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_getter, snapshot_cgp_type, snapshot_check_components, + snapshot_delegate_components, + }; + + snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } - #[cgp_type] - pub trait HasBarType { - type Bar; + snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } - #[cgp_getter { - provider: FooGetterAt, - }] - pub trait HasFooAt: HasFooType { - fn foo(&self, _tag: PhantomData) -> &Self::Foo; + snapshot_cgp_getter! { + #[cgp_getter { + provider: FooGetterAt, + }] + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + + expand_has_foo_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + impl<__Context__, I: Clone> HasFooAt for __Context__ + where + __Context__: HasFooType, + __Context__: FooGetterAt<__Context__, I>, + { + fn foo(&self, _tag: PhantomData) -> &Self::Foo { + __Context__::foo(self, _tag) + } + } + pub trait FooGetterAt< + __Context__, + I: Clone, + >: IsProviderFor + where + __Context__: HasFooType, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo; + } + impl<__Provider__, __Context__, I: Clone> FooGetterAt<__Context__, I> for __Provider__ + where + __Context__: HasFooType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate: FooGetterAt<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct FooGetterAtComponent; + impl<__Context__, I: Clone> FooGetterAt<__Context__, I> for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + __Context__::foo(__context__, _tag) + } + } + impl<__Context__, I: Clone> IsProviderFor + for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + {} + impl<__Context__, I: Clone, __Components__, __Path__> FooGetterAt<__Context__, I> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: FooGetterAt<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I: Clone, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + FooGetterAt<__Context__, I>, + {} + impl<__Context__, I: Clone> FooGetterAt<__Context__, I> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__, I: Clone> IsProviderFor + for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + {} + impl<__Context__, I: Clone, __Tag__> FooGetterAt<__Context__, I> for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl< + __Context__, + I: Clone, + __Tag__, + > IsProviderFor for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, I: Clone, __Provider__> FooGetterAt<__Context__, I> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl< + __Context__, + I: Clone, + __Provider__, + > IsProviderFor for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + {} + ") + } } - #[cgp_getter { - name: BarGetterAtComponent, - provider: BarGetterAt, - }] - pub trait HasBarAt: HasBarType { - fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + snapshot_cgp_getter! { + #[cgp_getter { + name: BarGetterAtComponent, + provider: BarGetterAt, + }] + pub trait HasBarAt: HasBarType { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + } + + expand_has_bar_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarAt: HasBarType { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar; + } + impl<__Context__, I: Clone, J> HasBarAt for __Context__ + where + __Context__: HasBarType, + __Context__: BarGetterAt<__Context__, I, J>, + { + fn foo(&self, _tag: PhantomData<(I, J)>) -> &Self::Bar { + __Context__::foo(self, _tag) + } + } + pub trait BarGetterAt< + __Context__, + I: Clone, + J, + >: IsProviderFor, __Context__, (I, J)> + where + __Context__: HasBarType, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar; + } + impl<__Provider__, __Context__, I: Clone, J> BarGetterAt<__Context__, I, J> + for __Provider__ + where + __Context__: HasBarType, + __Provider__: DelegateComponent> + + IsProviderFor, __Context__, (I, J)>, + <__Provider__ as DelegateComponent< + BarGetterAtComponent, + >>::Delegate: BarGetterAt<__Context__, I, J>, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + BarGetterAtComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct BarGetterAtComponent(pub ::core::marker::PhantomData<(I)>); + impl<__Context__, I: Clone, J> BarGetterAt<__Context__, I, J> for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + __Context__::foo(__context__, _tag) + } + } + impl< + __Context__, + I: Clone, + J, + > IsProviderFor, __Context__, (I, J)> for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + {} + impl<__Context__, I: Clone, J, __Components__, __Path__> BarGetterAt<__Context__, I, J> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: BarGetterAt<__Context__, I, J>, + { + fn foo(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Bar { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I: Clone, + J, + __Components__, + __Path__, + > IsProviderFor, __Context__, (I, J)> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: IsProviderFor, __Context__, (I, J)> + + BarGetterAt<__Context__, I, J>, + {} + impl<__Context__, I: Clone, J> BarGetterAt<__Context__, I, J> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Bar, + >, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl< + __Context__, + I: Clone, + J, + > IsProviderFor, __Context__, (I, J)> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Bar, + >, + {} + impl<__Context__, I: Clone, J, __Tag__> BarGetterAt<__Context__, I, J> + for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl< + __Context__, + I: Clone, + J, + __Tag__, + > IsProviderFor, __Context__, (I, J)> for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, I: Clone, J, __Provider__> BarGetterAt<__Context__, I, J> + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterAtComponent, + Value = __Context__::Bar, + >, + { + fn foo( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::>, + ) + } + } + impl< + __Context__, + I: Clone, + J, + __Provider__, + > IsProviderFor, __Context__, (I, J)> + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterAtComponent, + Value = __Context__::Bar, + >, + {} + ") + } } #[derive(HasField)] @@ -156,28 +1386,99 @@ pub fn test_generic_check_components() { pub dummy: (), } - delegate_components! { - Context { - [ - FooTypeProviderComponent, - BarTypeProviderComponent, - ]: - UseType<()>, - [ - FooGetterAtComponent, - BarGetterAtComponent, - ]: - UseField, + snapshot_delegate_components! { + delegate_components! { + Context { + [ + FooTypeProviderComponent, + BarTypeProviderComponent, + ]: + UseType<()>, + [ + FooGetterAtComponent, + BarGetterAtComponent, + ]: + UseField, + } + } + + expand_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for Context { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for Context { + type Delegate = UseType<()>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseType<()>: IsProviderFor, + {} + impl DelegateComponent for Context { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Context + where + UseField< + Symbol!("dummy"), + >: IsProviderFor, + {} + impl DelegateComponent> for Context { + type Delegate = UseField; + } + impl< + I, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for Context + where + UseField< + Symbol!("dummy"), + >: IsProviderFor, __Context__, __Params__>, + {} + "#) } } - check_components! { - <'a, I> Context - where - I: Clone, - { - FooGetterAtComponent: &'a I, - BarGetterAtComponent: (I, &'a Index<0>), + snapshot_check_components! { + check_components! { + <'a, I> Context + where + I: Clone, + { + FooGetterAtComponent: &'a I, + BarGetterAtComponent: (I, &'a Index<0>), + } + } + + expand_check_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl<'a, I> __CheckContext for Context + where + I: Clone, + {} + impl<'a, I> __CheckContext, (I, &'a Index<0>)> for Context + where + I: Clone, + {} + ") } } } diff --git a/crates/tests/cgp-tests/src/tests/compose.rs b/crates/tests/cgp-tests/src/tests/compose.rs index 2ca25ba5..79eac769 100644 --- a/crates/tests/cgp-tests/src/tests/compose.rs +++ b/crates/tests/cgp-tests/src/tests/compose.rs @@ -2,6 +2,7 @@ use core::fmt::Display; use cgp::extra::handler::{ComputerRef, ComputerRefComponent}; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_new_provider; pub fn first_name_to_string(context: &Context) -> String where @@ -33,43 +34,132 @@ pub fn concate_outputs( move |context| format!("{} {}", fn_a(context), fn_b(context)) } -#[cgp_new_provider] -impl ComputerRef for FirstNameToString -where - Context: HasField, -{ - type Output = String; +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl ComputerRef for FirstNameToString + where + Context: HasField, + { + type Output = String; - fn compute_ref(context: &Context, _code: PhantomData, _input: &Input) -> String { - context.get_field(PhantomData).to_string() + fn compute_ref(context: &Context, _code: PhantomData, _input: &Input) -> String { + context.get_field(PhantomData).to_string() + } + } + + expand_first_name_to_string(output) { + insta::assert_snapshot!(output, @r#" + impl ComputerRef for FirstNameToString + where + Context: HasField, + { + type Output = String; + fn compute_ref( + context: &Context, + _code: PhantomData, + _input: &Input, + ) -> String { + context.get_field(PhantomData).to_string() + } + } + impl IsProviderFor + for FirstNameToString + where + Context: HasField, + {} + pub struct FirstNameToString; + "#) } } -#[cgp_new_provider] -impl ComputerRef for LastNameToString -where - Context: HasField, -{ - type Output = String; +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl ComputerRef for LastNameToString + where + Context: HasField, + { + type Output = String; + + fn compute_ref(context: &Context, _code: PhantomData, _input: &Input) -> String { + context.get_field(PhantomData).to_string() + } + } - fn compute_ref(context: &Context, _code: PhantomData, _input: &Input) -> String { - context.get_field(PhantomData).to_string() + expand_last_name_to_string(output) { + insta::assert_snapshot!(output, @r#" + impl ComputerRef for LastNameToString + where + Context: HasField, + { + type Output = String; + fn compute_ref( + context: &Context, + _code: PhantomData, + _input: &Input, + ) -> String { + context.get_field(PhantomData).to_string() + } + } + impl IsProviderFor + for LastNameToString + where + Context: HasField, + {} + pub struct LastNameToString; + "#) } } -#[cgp_new_provider] -impl ComputerRef - for ConcatOutputs -where - ProviderA: ComputerRef, - ProviderB: ComputerRef, -{ - type Output = String; +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl ComputerRef + for ConcatOutputs + where + ProviderA: ComputerRef, + ProviderB: ComputerRef, + { + type Output = String; + + fn compute_ref(context: &Context, code: PhantomData, input: &Input) -> String { + let output_a = ProviderA::compute_ref(context, code, input); + let output_b = ProviderB::compute_ref(context, code, input); + format!("{output_a} {output_b}") + } + } - fn compute_ref(context: &Context, code: PhantomData, input: &Input) -> String { - let output_a = ProviderA::compute_ref(context, code, input); - let output_b = ProviderB::compute_ref(context, code, input); - format!("{output_a} {output_b}") + expand_concat_outputs(output) { + insta::assert_snapshot!(output, @r#" + impl ComputerRef + for ConcatOutputs + where + ProviderA: ComputerRef, + ProviderB: ComputerRef, + { + type Output = String; + fn compute_ref(context: &Context, code: PhantomData, input: &Input) -> String { + let output_a = ProviderA::compute_ref(context, code, input); + let output_b = ProviderB::compute_ref(context, code, input); + format!("{output_a} {output_b}") + } + } + impl< + Context, + Code, + Input, + ProviderA, + ProviderB, + > IsProviderFor + for ConcatOutputs + where + ProviderA: IsProviderFor + + ComputerRef, + ProviderB: IsProviderFor + + ComputerRef, + {} + pub struct ConcatOutputs( + pub ::core::marker::PhantomData<(ProviderA, ProviderB)>, + ); + "#) } } diff --git a/crates/tests/cgp-tests/src/tests/delegate_and_check_components.rs b/crates/tests/cgp-tests/src/tests/delegate_and_check_components.rs index b43e2827..956e1967 100644 --- a/crates/tests/cgp-tests/src/tests/delegate_and_check_components.rs +++ b/crates/tests/cgp-tests/src/tests/delegate_and_check_components.rs @@ -1,16 +1,264 @@ #![allow(dead_code)] -use cgp::prelude::*; +mod basic_delegate_and_check_components { + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_getter, snapshot_cgp_type, snapshot_delegate_and_check_components, + }; -pub fn test_basic_delegate_and_check_components() { - #[cgp_type] - pub trait HasNameType { - type Name; + snapshot_cgp_type! { + #[cgp_type] + pub trait HasNameType { + type Name; + } + + expand_has_name_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasNameType { + type Name; + } + impl<__Context__> HasNameType for __Context__ + where + __Context__: NameTypeProvider<__Context__>, + { + type Name = <__Context__ as NameTypeProvider<__Context__>>::Name; + } + pub trait NameTypeProvider< + __Context__, + >: IsProviderFor { + type Name; + } + impl<__Provider__, __Context__> NameTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + pub struct NameTypeProviderComponent; + impl<__Context__> NameTypeProvider<__Context__> for UseContext + where + __Context__: HasNameType, + { + type Name = <__Context__ as HasNameType>::Name; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasNameType, + {} + impl<__Context__, __Components__, __Path__> NameTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameTypeProvider<__Context__>, + {} + impl NameTypeProvider<__Context__> for UseType + where + Name:, + { + type Name = Name; + } + impl IsProviderFor + for UseType + where + Name:, + {} + impl<__Provider__, Name, __Context__> NameTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + { + type Name = Name; + } + impl< + __Provider__, + Name, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + {} + ") + } } - #[cgp_getter] - pub trait HasName: HasNameType { - fn name(&self) -> &Self::Name; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName: HasNameType { + fn name(&self) -> &Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName: HasNameType { + fn name(&self) -> &Self::Name; + } + impl<__Context__> HasName for __Context__ + where + __Context__: HasNameType, + __Context__: NameGetter<__Context__>, + { + fn name(&self) -> &Self::Name { + __Context__::name(self) + } + } + pub trait NameGetter<__Context__>: IsProviderFor + where + __Context__: HasNameType, + { + fn name(__context__: &__Context__) -> &__Context__::Name; + } + impl<__Provider__, __Context__> NameGetter<__Context__> for __Provider__ + where + __Context__: HasNameType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate::name(__context__) + } + } + pub struct NameGetterComponent; + impl<__Context__> NameGetter<__Context__> for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __Context__::name(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + {} + impl<__Context__, __Components__, __Path__> NameGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + <__Components__ as DelegateComponent<__Path__>>::Delegate::name(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameGetter<__Context__>, + {} + impl<__Context__> NameGetter<__Context__> for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + {} + impl<__Context__, __Tag__> NameGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + {} + impl<__Context__, __Provider__> NameGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + {} + ") + } } #[derive(HasField)] @@ -18,24 +266,307 @@ pub fn test_basic_delegate_and_check_components() { pub name: String, } - delegate_and_check_components! { - #[check_trait(CheckMyContext)] - MyContext { - NameTypeProviderComponent: UseType, - NameGetterComponent: UseField, + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + #[check_trait(CheckMyContext)] + MyContext { + NameTypeProviderComponent: UseType, + NameGetterComponent: UseField, + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseType: IsProviderFor, + {} + impl DelegateComponent for MyContext { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for MyContext + where + UseField< + Symbol!("name"), + >: IsProviderFor, + {} + trait CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CheckMyContext for MyContext {} + impl CheckMyContext for MyContext {} + "#) } } } -pub fn test_generic_delegate_and_check_components() { - #[cgp_type] - pub trait HasNameType { - type Name; +mod generic_delegate_and_check_components { + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_getter, snapshot_cgp_type, snapshot_delegate_and_check_components, + }; + + snapshot_cgp_type! { + #[cgp_type] + pub trait HasNameType { + type Name; + } + + expand_has_name_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasNameType { + type Name; + } + impl<__Context__> HasNameType for __Context__ + where + __Context__: NameTypeProvider<__Context__>, + { + type Name = <__Context__ as NameTypeProvider<__Context__>>::Name; + } + pub trait NameTypeProvider< + __Context__, + >: IsProviderFor { + type Name; + } + impl<__Provider__, __Context__> NameTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + pub struct NameTypeProviderComponent; + impl<__Context__> NameTypeProvider<__Context__> for UseContext + where + __Context__: HasNameType, + { + type Name = <__Context__ as HasNameType>::Name; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasNameType, + {} + impl<__Context__, __Components__, __Path__> NameTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameTypeProvider<__Context__>, + {} + impl NameTypeProvider<__Context__> for UseType + where + Name:, + { + type Name = Name; + } + impl IsProviderFor + for UseType + where + Name:, + {} + impl<__Provider__, Name, __Context__> NameTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + { + type Name = Name; + } + impl< + __Provider__, + Name, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + {} + ") + } } - #[cgp_getter] - pub trait HasName: HasNameType { - fn name(&self) -> &Self::Name; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName: HasNameType { + fn name(&self) -> &Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName: HasNameType { + fn name(&self) -> &Self::Name; + } + impl<__Context__> HasName for __Context__ + where + __Context__: HasNameType, + __Context__: NameGetter<__Context__>, + { + fn name(&self) -> &Self::Name { + __Context__::name(self) + } + } + pub trait NameGetter<__Context__>: IsProviderFor + where + __Context__: HasNameType, + { + fn name(__context__: &__Context__) -> &__Context__::Name; + } + impl<__Provider__, __Context__> NameGetter<__Context__> for __Provider__ + where + __Context__: HasNameType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate::name(__context__) + } + } + pub struct NameGetterComponent; + impl<__Context__> NameGetter<__Context__> for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __Context__::name(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + {} + impl<__Context__, __Components__, __Path__> NameGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + <__Components__ as DelegateComponent<__Path__>>::Delegate::name(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameGetter<__Context__>, + {} + impl<__Context__> NameGetter<__Context__> for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + {} + impl<__Context__, __Tag__> NameGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + {} + impl<__Context__, __Provider__> NameGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> &__Context__::Name { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + {} + ") + } } #[derive(HasField)] @@ -43,11 +574,48 @@ pub fn test_generic_delegate_and_check_components() { pub name: T, } - delegate_and_check_components! { - - MyContext { - NameTypeProviderComponent: UseType, - NameGetterComponent: UseField, + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + + MyContext { + NameTypeProviderComponent: UseType, + NameGetterComponent: UseField, + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = UseType; + } + impl< + T, + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseType: IsProviderFor, + {} + impl DelegateComponent for MyContext { + type Delegate = UseField; + } + impl< + T, + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseField< + Symbol!("name"), + >: IsProviderFor, + {} + trait __CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseMyContext for MyContext {} + impl __CanUseMyContext for MyContext {} + "#) } } } diff --git a/crates/tests/cgp-tests/src/tests/has_field/chain.rs b/crates/tests/cgp-tests/src/tests/has_field/chain.rs index 2d6119d9..c606a256 100644 --- a/crates/tests/cgp-tests/src/tests/has_field/chain.rs +++ b/crates/tests/cgp-tests/src/tests/has_field/chain.rs @@ -76,8 +76,11 @@ fn test_chained_getter_with_inner_life() { assert_eq!(name, "test"); } -#[test] -fn test_deeply_nested_getter() { +mod deeply_nested_getter { + use cgp::core::field::impls::ChainGetters; + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_and_check_components}; + #[derive(HasField)] pub struct A { pub b: B, @@ -103,35 +106,197 @@ fn test_deeply_nested_getter() { pub a: A, } - #[cgp_getter] - pub trait HasName { - fn name(&self) -> &str; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName { + fn name(&self) -> &str; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName { + fn name(&self) -> &str; + } + impl<__Context__> HasName for __Context__ + where + __Context__: NameGetter<__Context__>, + { + fn name(&self) -> &str { + __Context__::name(self) + } + } + pub trait NameGetter<__Context__>: IsProviderFor { + fn name(__context__: &__Context__) -> &str; + } + impl<__Provider__, __Context__> NameGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &str { + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate::name(__context__) + } + } + pub struct NameGetterComponent; + impl<__Context__> NameGetter<__Context__> for UseContext + where + __Context__: HasName, + { + fn name(__context__: &__Context__) -> &str { + __Context__::name(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasName, + {} + impl<__Context__, __Components__, __Path__> NameGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> &str { + <__Components__ as DelegateComponent<__Path__>>::Delegate::name(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameGetter<__Context__>, + {} + impl<__Context__> NameGetter<__Context__> for UseFields + where + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + { + fn name(__context__: &__Context__) -> &str { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .as_str() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + {} + impl<__Context__, __Tag__> NameGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + { + fn name(__context__: &__Context__) -> &str { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_str() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + {} + impl<__Context__, __Provider__> NameGetter<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, NameGetterComponent, Value = String>, + { + fn name(__context__: &__Context__) -> &str { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_str() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, NameGetterComponent, Value = String>, + {} + ") + } } - delegate_and_check_components! { - MyContext { - NameGetterComponent: WithProvider< - ChainGetters, - UseField, - UseField, - UseField, - UseField - ]>> + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + MyContext { + NameGetterComponent: WithProvider< + ChainGetters, + UseField, + UseField, + UseField, + UseField + ]>> + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = WithProvider< + ChainGetters< + Product![ + UseField < Symbol!("a") >, UseField < Symbol!("b") >, UseField < + Symbol!("c") >, UseField < Symbol!("d") >, UseField < Symbol!("name") > + ], + >, + >; + } + impl<__Context__, __Params__> IsProviderFor + for MyContext + where + WithProvider< + ChainGetters< + Product![ + UseField < Symbol!("a") >, UseField < Symbol!("b") >, UseField < + Symbol!("c") >, UseField < Symbol!("d") >, UseField < Symbol!("name") > + ], + >, + >: IsProviderFor, + {} + trait __CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseMyContext for MyContext {} + "#) } } - let context = MyContext { - a: A { - b: B { - c: C { - d: D { - name: "test".to_owned(), + #[test] + fn test_deeply_nested_getter() { + let context = MyContext { + a: A { + b: B { + c: C { + d: D { + name: "test".to_owned(), + }, }, }, }, - }, - }; + }; - assert_eq!(context.name(), "test"); + assert_eq!(context.name(), "test"); + } } diff --git a/crates/tests/cgp-tests/src/tests/use_delegate/getter.rs b/crates/tests/cgp-tests/src/tests/use_delegate/getter.rs index 01ebf26d..f40b5064 100644 --- a/crates/tests/cgp-tests/src/tests/use_delegate/getter.rs +++ b/crates/tests/cgp-tests/src/tests/use_delegate/getter.rs @@ -1,123 +1,744 @@ use core::marker::PhantomData; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_cgp_type}; pub struct UseDelegate2(pub PhantomData); -#[cgp_type { - provider: FooTypeProviderAt, - derive_delegate: [ - UseDelegate, - UseDelegate2<(I, J)>, - ], -}] -pub trait HasFooTypeAt { - type Foo; +snapshot_cgp_type! { + #[cgp_type { + provider: FooTypeProviderAt, + derive_delegate: [ + UseDelegate, + UseDelegate2<(I, J)>, + ], + }] + pub trait HasFooTypeAt { + type Foo; + } + + expand_has_foo_type_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooTypeAt { + type Foo; + } + impl<__Context__, I, J> HasFooTypeAt for __Context__ + where + __Context__: FooTypeProviderAt<__Context__, I, J>, + { + type Foo = <__Context__ as FooTypeProviderAt<__Context__, I, J>>::Foo; + } + pub trait FooTypeProviderAt< + __Context__, + I, + J, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__, I, J> FooTypeProviderAt<__Context__, I, J> + for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderAtComponent, + >>::Delegate: FooTypeProviderAt<__Context__, I, J>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderAtComponent, + >>::Delegate as FooTypeProviderAt<__Context__, I, J>>::Foo; + } + pub struct FooTypeProviderAtComponent; + impl<__Context__, I, J> FooTypeProviderAt<__Context__, I, J> for UseContext + where + __Context__: HasFooTypeAt, + { + type Foo = <__Context__ as HasFooTypeAt>::Foo; + } + impl<__Context__, I, J> IsProviderFor + for UseContext + where + __Context__: HasFooTypeAt, + {} + impl<__Context__, I, J, __Components__, __Path__> FooTypeProviderAt<__Context__, I, J> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: FooTypeProviderAt<__Context__, I, J>, + { + type Foo = <<__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate as FooTypeProviderAt<__Context__, I, J>>::Foo; + } + impl< + __Context__, + I, + J, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: IsProviderFor + + FooTypeProviderAt<__Context__, I, J>, + {} + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > FooTypeProviderAt<__Context__, I, J> for UseDelegate<__Components__> + where + __Components__: DelegateComponent<(I), Delegate = __Delegate__>, + __Delegate__: FooTypeProviderAt<__Context__, I, J>, + { + type Foo = <__Delegate__ as FooTypeProviderAt<__Context__, I, J>>::Foo; + } + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > IsProviderFor + for UseDelegate<__Components__> + where + __Components__: DelegateComponent<(I), Delegate = __Delegate__>, + __Delegate__: IsProviderFor + + FooTypeProviderAt<__Context__, I, J>, + {} + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > FooTypeProviderAt<__Context__, I, J> for UseDelegate2<__Components__> + where + __Components__: DelegateComponent<(I, J), Delegate = __Delegate__>, + __Delegate__: FooTypeProviderAt<__Context__, I, J>, + { + type Foo = <__Delegate__ as FooTypeProviderAt<__Context__, I, J>>::Foo; + } + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > IsProviderFor + for UseDelegate2<__Components__> + where + __Components__: DelegateComponent<(I, J), Delegate = __Delegate__>, + __Delegate__: IsProviderFor + + FooTypeProviderAt<__Context__, I, J>, + {} + impl FooTypeProviderAt<__Context__, I, J> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl< + Foo, + __Context__, + I, + J, + > IsProviderFor for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__, I, J> FooTypeProviderAt<__Context__, I, J> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderAtComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + I, + J, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderAtComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_getter { - provider: FooGetterAt, - derive_delegate: [ - UseDelegate, - UseDelegate2<(I, J)>, - ], -}] -pub trait HasFooAt: HasFooTypeAt { - fn foo_at(&self, _tag: PhantomData<(I, J)>) -> &Self::Foo; +snapshot_cgp_getter! { + #[cgp_getter { + provider: FooGetterAt, + derive_delegate: [ + UseDelegate, + UseDelegate2<(I, J)>, + ], + }] + pub trait HasFooAt: HasFooTypeAt { + fn foo_at(&self, _tag: PhantomData<(I, J)>) -> &Self::Foo; + } + + expand_has_foo_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooAt: HasFooTypeAt { + fn foo_at(&self, _tag: PhantomData<(I, J)>) -> &Self::Foo; + } + impl<__Context__, I, J> HasFooAt for __Context__ + where + __Context__: HasFooTypeAt, + __Context__: FooGetterAt<__Context__, I, J>, + { + fn foo_at(&self, _tag: PhantomData<(I, J)>) -> &Self::Foo { + __Context__::foo_at(self, _tag) + } + } + pub trait FooGetterAt< + __Context__, + I, + J, + >: IsProviderFor + where + __Context__: HasFooTypeAt, + { + fn foo_at(__context__: &__Context__, _tag: PhantomData<(I, J)>) -> &__Context__::Foo; + } + impl<__Provider__, __Context__, I, J> FooGetterAt<__Context__, I, J> for __Provider__ + where + __Context__: HasFooTypeAt, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate: FooGetterAt<__Context__, I, J>, + { + fn foo_at( + __context__: &__Context__, + _tag: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterAtComponent, + >>::Delegate::foo_at(__context__, _tag) + } + } + pub struct FooGetterAtComponent; + impl<__Context__, I, J> FooGetterAt<__Context__, I, J> for UseContext + where + __Context__: HasFooTypeAt, + __Context__: HasFooAt, + { + fn foo_at( + __context__: &__Context__, + _tag: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __Context__::foo_at(__context__, _tag) + } + } + impl<__Context__, I, J> IsProviderFor + for UseContext + where + __Context__: HasFooTypeAt, + __Context__: HasFooAt, + {} + impl<__Context__, I, J, __Components__, __Path__> FooGetterAt<__Context__, I, J> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooTypeAt, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: FooGetterAt<__Context__, I, J>, + { + fn foo_at( + __context__: &__Context__, + _tag: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate::foo_at(__context__, _tag) + } + } + impl< + __Context__, + I, + J, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooTypeAt, + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: IsProviderFor + + FooGetterAt<__Context__, I, J>, + {} + impl<__Context__, I, J, __Components__, __Delegate__> FooGetterAt<__Context__, I, J> + for UseDelegate<__Components__> + where + __Context__: HasFooTypeAt, + __Components__: DelegateComponent<(I), Delegate = __Delegate__>, + __Delegate__: FooGetterAt<__Context__, I, J>, + { + fn foo_at( + __context__: &__Context__, + _tag: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __Delegate__::foo_at(__context__, _tag) + } + } + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > IsProviderFor + for UseDelegate<__Components__> + where + __Context__: HasFooTypeAt, + __Components__: DelegateComponent<(I), Delegate = __Delegate__>, + __Delegate__: IsProviderFor + + FooGetterAt<__Context__, I, J>, + {} + impl<__Context__, I, J, __Components__, __Delegate__> FooGetterAt<__Context__, I, J> + for UseDelegate2<__Components__> + where + __Context__: HasFooTypeAt, + __Components__: DelegateComponent<(I, J), Delegate = __Delegate__>, + __Delegate__: FooGetterAt<__Context__, I, J>, + { + fn foo_at( + __context__: &__Context__, + _tag: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __Delegate__::foo_at(__context__, _tag) + } + } + impl< + __Context__, + I, + J, + __Components__, + __Delegate__, + > IsProviderFor + for UseDelegate2<__Components__> + where + __Context__: HasFooTypeAt, + __Components__: DelegateComponent<(I, J), Delegate = __Delegate__>, + __Delegate__: IsProviderFor + + FooGetterAt<__Context__, I, J>, + {} + impl<__Context__, I, J> FooGetterAt<__Context__, I, J> for UseFields + where + __Context__: HasFooTypeAt, + __Context__: HasField< + Symbol< + 6, + Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'a', Chars<'t', Nil>>>>>>, + >, + Value = __Context__::Foo, + >, + { + fn foo_at( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'f', + Chars< + 'o', + Chars<'o', Chars<'_', Chars<'a', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + } + } + impl<__Context__, I, J> IsProviderFor + for UseFields + where + __Context__: HasFooTypeAt, + __Context__: HasField< + Symbol< + 6, + Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'a', Chars<'t', Nil>>>>>>, + >, + Value = __Context__::Foo, + >, + {} + impl<__Context__, I, J, __Tag__> FooGetterAt<__Context__, I, J> for UseField<__Tag__> + where + __Context__: HasFooTypeAt, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo_at( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, J, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasFooTypeAt, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, I, J, __Provider__> FooGetterAt<__Context__, I, J> + for WithProvider<__Provider__> + where + __Context__: HasFooTypeAt, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + { + fn foo_at( + __context__: &__Context__, + _phantom: PhantomData<(I, J)>, + ) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl< + __Context__, + I, + J, + __Provider__, + > IsProviderFor for WithProvider<__Provider__> + where + __Context__: HasFooTypeAt, + __Provider__: FieldGetter< + __Context__, + FooGetterAtComponent, + Value = __Context__::Foo, + >, + {} + ") + } } -#[test] -pub fn test_derive_delegate() { +mod derive_delegate { + use core::marker::PhantomData; + + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_and_check_components}; + + use super::*; + #[derive(HasField)] pub struct MyContext { pub foo: u64, pub bar: String, } - delegate_and_check_components! { - MyContext { - #[check_params( - (Index<1>, Index<0>), - (Index<0>, Index<1>), - )] - FooTypeProviderAtComponent: UseDelegate< - new FooTypes { - Index<1>: UseType, - Index<0>: UseType, - } - >, + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + MyContext { + #[check_params( + (Index<1>, Index<0>), + (Index<0>, Index<1>), + )] + FooTypeProviderAtComponent: UseDelegate< + new FooTypes { + Index<1>: UseType, + Index<0>: UseType, + } + >, + + #[check_params( + (Index<1>, Index<0>), + (Index<0>, Index<1>), + )] + FooGetterAtComponent: UseDelegate< + new FooGetters { + Index<1>: UseField, + Index<0>: UseField, + } + > + } + } - #[check_params( - (Index<1>, Index<0>), - (Index<0>, Index<1>), - )] - FooGetterAtComponent: UseDelegate< - new FooGetters { - Index<1>: UseField, - Index<0>: UseField, - } - > + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = UseDelegate; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseDelegate< + FooTypes, + >: IsProviderFor, + {} + pub struct FooTypes; + impl DelegateComponent> for FooTypes { + type Delegate = UseType; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooTypes + where + UseType: IsProviderFor, __Context__, __Params__>, + {} + impl DelegateComponent> for FooTypes { + type Delegate = UseType; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooTypes + where + UseType: IsProviderFor, __Context__, __Params__>, + {} + impl DelegateComponent for MyContext { + type Delegate = UseDelegate; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseDelegate< + FooGetters, + >: IsProviderFor, + {} + pub struct FooGetters; + impl DelegateComponent> for FooGetters { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooGetters + where + UseField: IsProviderFor, __Context__, __Params__>, + {} + impl DelegateComponent> for FooGetters { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooGetters + where + UseField: IsProviderFor, __Context__, __Params__>, + {} + trait __CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseMyContext, Index<0>)> for MyContext {} + impl __CanUseMyContext, Index<1>)> for MyContext {} + impl __CanUseMyContext, Index<0>)> for MyContext {} + impl __CanUseMyContext, Index<1>)> for MyContext {} + "#) } } - check_components! { - #[check_trait(CanUseMyContext)] - MyContext { - FooGetterAtComponent: [ - (Index<1>, Index<0>), - (Index<0>, Index<1>), - ] + snapshot_check_components! { + check_components! { + #[check_trait(CanUseMyContext)] + MyContext { + FooGetterAtComponent: [ + (Index<1>, Index<0>), + (Index<0>, Index<1>), + ] + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseMyContext, Index<0>)> for MyContext {} + impl CanUseMyContext, Index<1>)> for MyContext {} + ") } } - let context = MyContext { - foo: 42, - bar: "Bar".into(), - }; + #[test] + pub fn test_derive_delegate() { + let context = MyContext { + foo: 42, + bar: "Bar".into(), + }; - assert_eq!(context.foo_at(PhantomData::<(Index<1>, Index<0>)>), &42); - assert_eq!(context.foo_at(PhantomData::<(Index<0>, Index<1>)>), "Bar"); + assert_eq!(context.foo_at(PhantomData::<(Index<1>, Index<0>)>), &42); + assert_eq!(context.foo_at(PhantomData::<(Index<0>, Index<1>)>), "Bar"); + } } -#[test] -pub fn test_derive_delegate2() { +mod derive_delegate2 { + use core::marker::PhantomData; + + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_components}; + + use super::*; + #[derive(HasField)] pub struct MyContext { pub foo: u64, pub bar: String, } - delegate_components! { - MyContext { - FooTypeProviderAtComponent: UseDelegate2< - new FooTypes { - (Index<1>, Index<0>): UseType, - (Index<0>, Index<1>): UseType, - } - >, - FooGetterAtComponent: UseDelegate2< - new FooGetters { - (Index<1>, Index<0>): UseField, - (Index<0>, Index<1>): UseField, - } - > + snapshot_delegate_components! { + delegate_components! { + MyContext { + FooTypeProviderAtComponent: UseDelegate2< + new FooTypes { + (Index<1>, Index<0>): UseType, + (Index<0>, Index<1>): UseType, + } + >, + FooGetterAtComponent: UseDelegate2< + new FooGetters { + (Index<1>, Index<0>): UseField, + (Index<0>, Index<1>): UseField, + } + > + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + pub struct FooTypes; + pub struct FooGetters; + impl DelegateComponent for MyContext { + type Delegate = UseDelegate2; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseDelegate2< + FooTypes, + >: IsProviderFor, + {} + impl DelegateComponent for MyContext { + type Delegate = UseDelegate2; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseDelegate2< + FooGetters, + >: IsProviderFor, + {} + impl DelegateComponent<(Index<1>, Index<0>)> for FooTypes { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor<(Index<1>, Index<0>), __Context__, __Params__> for FooTypes + where + UseType: IsProviderFor<(Index<1>, Index<0>), __Context__, __Params__>, + {} + impl DelegateComponent<(Index<0>, Index<1>)> for FooTypes { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor<(Index<0>, Index<1>), __Context__, __Params__> for FooTypes + where + UseType: IsProviderFor<(Index<0>, Index<1>), __Context__, __Params__>, + {} + impl DelegateComponent<(Index<1>, Index<0>)> for FooGetters { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor<(Index<1>, Index<0>), __Context__, __Params__> for FooGetters + where + UseField< + Symbol!("foo"), + >: IsProviderFor<(Index<1>, Index<0>), __Context__, __Params__>, + {} + impl DelegateComponent<(Index<0>, Index<1>)> for FooGetters { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor<(Index<0>, Index<1>), __Context__, __Params__> for FooGetters + where + UseField< + Symbol!("bar"), + >: IsProviderFor<(Index<0>, Index<1>), __Context__, __Params__>, + {} + "#) } } - check_components! { - MyContext { - FooGetterAtComponent: [ - (Index<1>, Index<0>), - (Index<0>, Index<1>), - ] + snapshot_check_components! { + check_components! { + MyContext { + FooGetterAtComponent: [ + (Index<1>, Index<0>), + (Index<0>, Index<1>), + ] + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext, Index<0>)> for MyContext {} + impl __CheckMyContext, Index<1>)> for MyContext {} + ") } } - let context = MyContext { - foo: 42, - bar: "Bar".into(), - }; + #[test] + pub fn test_derive_delegate2() { + let context = MyContext { + foo: 42, + bar: "Bar".into(), + }; - assert_eq!(context.foo_at(PhantomData::<(Index<1>, Index<0>)>), &42); - assert_eq!(context.foo_at(PhantomData::<(Index<0>, Index<1>)>), "Bar"); + assert_eq!(context.foo_at(PhantomData::<(Index<1>, Index<0>)>), &42); + assert_eq!(context.foo_at(PhantomData::<(Index<0>, Index<1>)>), "Bar"); + } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/async.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/async.rs index a4110246..b3647e80 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/async.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/async.rs @@ -1,7 +1,38 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -#[async_trait] -pub async fn greet(&self, #[implicit] name: &str) -> String { - format!("Hello, {}!", name) +snapshot_cgp_fn! { + #[cgp_fn] + #[async_trait] + pub async fn greet(&self, #[implicit] name: &str) -> String { + format!("Hello, {}!", name) + } + + expand_greet(output) { + insta::assert_snapshot!(output, @r#" + #[async_trait] + pub trait Greet { + async fn greet(&self) -> String; + } + #[async_trait] + impl<__Context__> Greet for __Context__ + where + Self: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + { + async fn greet(&self) -> String { + let name: &str = self + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .as_str(); + format!("Hello, {}!", name) + } + } + "#) + } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/basic.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/basic.rs index 2274c229..7a89d3f8 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/basic.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/basic.rs @@ -1,8 +1,37 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -pub fn greet(&self, #[implicit] name: &str) { - println!("Hello, {}!", name); +snapshot_cgp_fn! { + #[cgp_fn] + pub fn greet(&self, #[implicit] name: &str) { + println!("Hello, {}!", name); + } + + expand_greet(output) { + insta::assert_snapshot!(output, @r#" + pub trait Greet { + fn greet(&self); + } + impl<__Context__> Greet for __Context__ + where + Self: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + { + fn greet(&self) { + let name: &str = self + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .as_str(); + println!("Hello, {}!", name); + } + } + "#) + } } #[derive(HasField)] @@ -13,9 +42,66 @@ pub struct Person { pub trait CheckPerson: Greet {} impl CheckPerson for Person {} -#[cgp_fn(CanCalculateRectangleArea)] -pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_fn! { + #[cgp_fn(CanCalculateRectangleArea)] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait CanCalculateRectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> CanCalculateRectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn rectangle_area(&self) -> f64 { + let width: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/call.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/call.rs index c792c749..2eb15da6 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/call.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/call.rs @@ -1,16 +1,157 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn rectangle_area(&self) -> f64 { + let width: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } -#[cgp_fn] -pub fn scaled_rectangle_area(&self, #[implicit] scale_factor: f64) -> f64 -where - Self: RectangleArea, -{ - self.rectangle_area() * scale_factor * scale_factor +snapshot_cgp_fn! { + #[cgp_fn] + pub fn scaled_rectangle_area(&self, #[implicit] scale_factor: f64) -> f64 + where + Self: RectangleArea, + { + self.rectangle_area() * scale_factor * scale_factor + } + + expand_scaled_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait ScaledRectangleArea { + fn scaled_rectangle_area(&self) -> f64; + } + impl<__Context__> ScaledRectangleArea for __Context__ + where + Self: RectangleArea, + Self: HasField< + Symbol< + 12, + Chars< + 's', + Chars< + 'c', + Chars< + 'a', + Chars< + 'l', + Chars< + 'e', + Chars< + '_', + Chars< + 'f', + Chars< + 'a', + Chars<'c', Chars<'t', Chars<'o', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + >, + >, + >, + >, + Value = f64, + >, + { + fn scaled_rectangle_area(&self) -> f64 { + let scale_factor: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 12, + Chars< + 's', + Chars< + 'c', + Chars< + 'a', + Chars< + 'l', + Chars< + 'e', + Chars< + '_', + Chars< + 'f', + Chars< + 'a', + Chars<'c', Chars<'t', Chars<'o', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + ) + .clone(); + self.rectangle_area() * scale_factor * scale_factor + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/extend.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/extend.rs index 172729fa..531546c6 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/extend.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/extend.rs @@ -1,23 +1,182 @@ use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_fn] -#[extend(HasScalarType)] -pub fn rectangle_area( - &self, - #[implicit] width: Self::Scalar, - #[implicit] height: Self::Scalar, -) -> Self::Scalar -where - Self::Scalar: Mul + Copy, -{ - width * height +snapshot_cgp_fn! { + #[cgp_fn] + #[extend(HasScalarType)] + pub fn rectangle_area( + &self, + #[implicit] width: Self::Scalar, + #[implicit] height: Self::Scalar, + ) -> Self::Scalar + where + Self::Scalar: Mul + Copy, + { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasScalarType { + fn rectangle_area(&self) -> Self::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + Self::Scalar: Mul + Copy, + Self: HasScalarType, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = Self::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = Self::Scalar, + >, + { + fn rectangle_area(&self) -> Self::Scalar { + let width: Self::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: Self::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type.rs index 162b10d5..91d804fa 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type.rs @@ -1,24 +1,185 @@ use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_fn] -#[use_type(@Types::HasScalarType::Scalar)] -pub fn rectangle_area( - &self, - #[implicit] width: Scalar, - #[implicit] height: Scalar, -) -> Scalar -where - Scalar: Mul + Copy, -{ - let res: Scalar = width * height; - res +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(@Types::HasScalarType::Scalar)] + pub fn rectangle_area( + &self, + #[implicit] width: Scalar, + #[implicit] height: Scalar, + ) -> Scalar + where + Scalar: Mul + Copy, + { + let res: Scalar = width * height; + res + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> ::Scalar; + } + impl<__Context__, Types: HasScalarType> RectangleArea for __Context__ + where + ::Scalar: Mul::Scalar> + + Copy, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = ::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = ::Scalar, + >, + Types: HasScalarType, + { + fn rectangle_area(&self) -> ::Scalar { + let width: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + let res: ::Scalar = width * height; + res + } + } + ") + } } pub struct Types; diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type_equality.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type_equality.rs index 54b4a00b..bf76eb08 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type_equality.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/foreign_type_equality.rs @@ -1,23 +1,282 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_type] -pub trait HasTypes { - type Types: HasScalarType; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasTypes { + type Types: HasScalarType; + } + + expand_has_types(output) { + insta::assert_snapshot!(output, @" + pub trait HasTypes { + type Types: HasScalarType; + } + impl<__Context__> HasTypes for __Context__ + where + __Context__: TypesTypeProvider<__Context__>, + { + type Types = <__Context__ as TypesTypeProvider<__Context__>>::Types; + } + pub trait TypesTypeProvider< + __Context__, + >: IsProviderFor { + type Types: HasScalarType; + } + impl<__Provider__, __Context__> TypesTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + TypesTypeProviderComponent, + >>::Delegate: TypesTypeProvider<__Context__>, + { + type Types = <<__Provider__ as DelegateComponent< + TypesTypeProviderComponent, + >>::Delegate as TypesTypeProvider<__Context__>>::Types; + } + pub struct TypesTypeProviderComponent; + impl<__Context__> TypesTypeProvider<__Context__> for UseContext + where + __Context__: HasTypes, + { + type Types = <__Context__ as HasTypes>::Types; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasTypes, + {} + impl<__Context__, __Components__, __Path__> TypesTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: TypesTypeProvider<__Context__>, + { + type Types = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as TypesTypeProvider<__Context__>>::Types; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + TypesTypeProvider<__Context__>, + {} + impl TypesTypeProvider<__Context__> for UseType + where + Types: HasScalarType, + { + type Types = Types; + } + impl IsProviderFor + for UseType + where + Types: HasScalarType, + {} + impl<__Provider__, Types, __Context__> TypesTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, TypesTypeProviderComponent, Type = Types>, + Types: HasScalarType, + { + type Types = Types; + } + impl< + __Provider__, + Types, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, TypesTypeProviderComponent, Type = Types>, + Types: HasScalarType, + {} + ") + } } -#[cgp_fn] -#[use_type( - HasTypes::Types, - @Types::HasScalarType::{Scalar = f64}, -)] -pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar { - let res: f64 = width * height; - res +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type( + HasTypes::Types, + @Types::HasScalarType::{Scalar = f64}, + )] + pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar { + let res: f64 = width * height; + res + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasTypes { + fn rectangle_area(&self) -> <::Types as HasScalarType>::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <::Types as HasScalarType>::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = <::Types as HasScalarType>::Scalar, + >, + Self: HasTypes, + ::Types: HasScalarType, + { + fn rectangle_area(&self) -> <::Types as HasScalarType>::Scalar { + let width: <::Types as HasScalarType>::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: <::Types as HasScalarType>::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + let res: f64 = width * height; + res + } + } + ") + } } pub trait HasFooType { @@ -28,31 +287,115 @@ pub trait HasBarType { type Bar: HasFooType; } -#[cgp_fn] -#[use_type(HasFooType::Foo)] -pub fn do_foo(&self) -> Foo { - todo!() -} - -#[cgp_fn] -#[use_type(HasBarType::Bar, @Bar::HasFooType::Foo)] -pub fn do_bar(&self) -> Foo { - todo!() -} - -#[cgp_fn] -#[use_type( - HasFooType::Foo, - HasBarType::Bar, - @Bar::HasFooType::{Foo as BarFoo = Foo}, -)] -#[uses(DoFoo, DoBar)] -fn return_foo_or_bar(&self, flag: bool, #[implicit] foo: &Foo, #[implicit] bar: &BarFoo) -> Foo { - if flag { - let res: Foo = self.do_foo(); - if &res < foo { res } else { foo.clone() } - } else { - let res: BarFoo = self.do_bar(); - if &res < bar { res } else { bar.clone() } +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasFooType::Foo)] + pub fn do_foo(&self) -> Foo { + todo!() + } + + expand_do_foo(output) { + insta::assert_snapshot!(output, @" + pub trait DoFoo: HasFooType { + fn do_foo(&self) -> ::Foo; + } + impl<__Context__> DoFoo for __Context__ + where + Self: HasFooType, + { + fn do_foo(&self) -> ::Foo { + todo!() + } + } + ") + } +} + +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasBarType::Bar, @Bar::HasFooType::Foo)] + pub fn do_bar(&self) -> Foo { + todo!() + } + + expand_do_bar(output) { + insta::assert_snapshot!(output, @" + pub trait DoBar: HasBarType { + fn do_bar(&self) -> <::Bar as HasFooType>::Foo; + } + impl<__Context__> DoBar for __Context__ + where + Self: HasBarType, + ::Bar: HasFooType, + { + fn do_bar(&self) -> <::Bar as HasFooType>::Foo { + todo!() + } + } + ") + } +} + +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type( + HasFooType::Foo, + HasBarType::Bar, + @Bar::HasFooType::{Foo as BarFoo = Foo}, + )] + #[uses(DoFoo, DoBar)] + fn return_foo_or_bar(&self, flag: bool, #[implicit] foo: &Foo, #[implicit] bar: &BarFoo) -> Foo { + if flag { + let res: Foo = self.do_foo(); + if &res < foo { res } else { foo.clone() } + } else { + let res: BarFoo = self.do_bar(); + if &res < bar { res } else { bar.clone() } + } + } + + expand_return_foo_or_bar(output) { + insta::assert_snapshot!(output, @" + trait ReturnFooOrBar: HasFooType + HasBarType { + fn return_foo_or_bar(&self, flag: bool) -> ::Foo; + } + impl<__Context__> ReturnFooOrBar for __Context__ + where + Self: DoFoo + DoBar, + Self: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = ::Foo, + > + + HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = <::Bar as HasFooType>::Foo, + >, + Self: HasFooType, + Self: HasBarType, + ::Bar: HasFooType::Foo>, + { + fn return_foo_or_bar(&self, flag: bool) -> ::Foo { + let foo: &::Foo = self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ); + let bar: &<::Bar as HasFooType>::Foo = self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ); + if flag { + let res: ::Foo = self.do_foo(); + if &res < foo { res } else { foo.clone() } + } else { + let res: <::Bar as HasFooType>::Foo = self.do_bar(); + if &res < bar { res } else { bar.clone() } + } + } + } + ") } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/generics.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/generics.rs index baaae9f7..c9f1a0e9 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/generics.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/generics.rs @@ -1,17 +1,76 @@ use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -pub fn rectangle_area( - &self, - #[implicit] width: Scalar, - #[implicit] height: Scalar, -) -> Scalar -where - Scalar: Mul + Copy, -{ - width * height +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area( + &self, + #[implicit] width: Scalar, + #[implicit] height: Scalar, + ) -> Scalar + where + Scalar: Mul + Copy, + { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> Scalar; + } + impl<__Context__, Scalar> RectangleArea for __Context__ + where + Scalar: Mul + Copy, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = Scalar, + >, + { + fn rectangle_area(&self) -> Scalar { + let width: Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/impl_generics.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/impl_generics.rs index 65f0e629..af4bae12 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/impl_generics.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/impl_generics.rs @@ -1,20 +1,67 @@ use core::fmt::Display; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -#[impl_generics(Name: Display)] -pub fn greet(&self, #[implicit] name: &Name) -> String -where - Name: Display, -{ - format!("Hello, {}!", name) +snapshot_cgp_fn! { + #[cgp_fn] + #[impl_generics(Name: Display)] + pub fn greet(&self, #[implicit] name: &Name) -> String + where + Name: Display, + { + format!("Hello, {}!", name) + } + + expand_greet(output) { + insta::assert_snapshot!(output, @r#" + pub trait Greet { + fn greet(&self) -> String; + } + impl<__Context__, Name: Display> Greet for __Context__ + where + Name: Display, + Self: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = Name, + >, + { + fn greet(&self) -> String { + let name: &Name = self + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ); + format!("Hello, {}!", name) + } + } + "#) + } } -#[cgp_fn] -#[uses(Greet)] -pub fn test_greet(&self) { - assert_eq!(self.greet(), "Hello, John!"); +snapshot_cgp_fn! { + #[cgp_fn] + #[uses(Greet)] + pub fn test_greet(&self) { + assert_eq!(self.greet(), "Hello, John!"); + } + + expand_test_greet(output) { + insta::assert_snapshot!(output, @r#" + pub trait TestGreet { + fn test_greet(&self); + } + impl<__Context__> TestGreet for __Context__ + where + Self: Greet, + { + fn test_greet(&self) { + assert_eq!(self.greet(), "Hello, John!"); + } + } + "#) + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/multi.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/multi.rs index 5c93b406..6771f485 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/multi.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/multi.rs @@ -1,6 +1,7 @@ use core::fmt::Display; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; pub trait HasFooType { type Foo; @@ -12,20 +13,81 @@ pub trait HasBarType { type Baz; } -#[cgp_fn] -#[allow(unused)] -#[async_trait] -#[use_type(>::{Foo as FooX}, >::{Foo as FooY}, HasBarType::{Bar, Baz})] -pub async fn do_foo_bar( - &self, - x: X, - #[implicit] foo_x: &FooX, - #[implicit] foo_y: &FooY, - #[implicit] bar: &Bar, - y: Y, -) -> Option -where - FooX: Display, -{ - None +snapshot_cgp_fn! { + #[cgp_fn] + #[allow(unused)] + #[async_trait] + #[use_type(>::{Foo as FooX}, >::{Foo as FooY}, HasBarType::{Bar, Baz})] + pub async fn do_foo_bar( + &self, + x: X, + #[implicit] foo_x: &FooX, + #[implicit] foo_y: &FooY, + #[implicit] bar: &Bar, + y: Y, + ) -> Option + where + FooX: Display, + { + None + } + + expand_do_foo_bar(output) { + insta::assert_snapshot!(output, @" + #[allow(unused)] + #[async_trait] + pub trait DoFooBar: HasFooType + HasFooType + HasBarType { + async fn do_foo_bar(&self, x: X, y: Y) -> Option<::Baz>; + } + #[allow(unused)] + #[async_trait] + impl<__Context__, X, Y> DoFooBar for __Context__ + where + >::Foo: Display, + Self: HasField< + Symbol<5, Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'x', Nil>>>>>>, + Value = >::Foo, + > + + HasField< + Symbol<5, Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'y', Nil>>>>>>, + Value = >::Foo, + > + + HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = ::Bar, + >, + Self: HasFooType, + Self: HasFooType, + Self: HasBarType, + { + async fn do_foo_bar(&self, x: X, y: Y) -> Option<::Baz> { + let foo_x: &>::Foo = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'x', Nil>>>>>, + >, + >, + ); + let foo_y: &>::Foo = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'f', Chars<'o', Chars<'o', Chars<'_', Chars<'y', Nil>>>>>, + >, + >, + ); + let bar: &::Bar = self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ); + None + } + } + ") + } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/mutable.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/mutable.rs index 507d127d..36b96b43 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/mutable.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/mutable.rs @@ -1,13 +1,45 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -pub fn capitalize_name(&mut self, #[implicit] name: &mut String) { - if let Some(first_char) = name.chars().next() - && first_char.is_lowercase() - { - let char_len = first_char.len_utf8(); - let capitalized = first_char.to_uppercase().to_string(); - name.replace_range(..char_len, &capitalized); +snapshot_cgp_fn! { + #[cgp_fn] + pub fn capitalize_name(&mut self, #[implicit] name: &mut String) { + if let Some(first_char) = name.chars().next() + && first_char.is_lowercase() + { + let char_len = first_char.len_utf8(); + let capitalized = first_char.to_uppercase().to_string(); + name.replace_range(..char_len, &capitalized); + } + } + + expand_capitalize_name(output) { + insta::assert_snapshot!(output, @" + pub trait CapitalizeName { + fn capitalize_name(&mut self); + } + impl<__Context__> CapitalizeName for __Context__ + where + Self: HasFieldMut< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + { + fn capitalize_name(&mut self) { + let name: &mut String = self + .get_field_mut( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ); + if let Some(first_char) = name.chars().next() && first_char.is_lowercase() { + let char_len = first_char.len_utf8(); + let capitalized = first_char.to_uppercase().to_string(); + name.replace_range(..char_len, &capitalized); + } + } + } + ") } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/nested_foreign_type.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/nested_foreign_type.rs index 31da2d1b..f9669016 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/nested_foreign_type.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/nested_foreign_type.rs @@ -1,26 +1,292 @@ use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_type] -pub trait HasTypes { - type Types; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasTypes { + type Types; + } + + expand_has_types(output) { + insta::assert_snapshot!(output, @" + pub trait HasTypes { + type Types; + } + impl<__Context__> HasTypes for __Context__ + where + __Context__: TypesTypeProvider<__Context__>, + { + type Types = <__Context__ as TypesTypeProvider<__Context__>>::Types; + } + pub trait TypesTypeProvider< + __Context__, + >: IsProviderFor { + type Types; + } + impl<__Provider__, __Context__> TypesTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + TypesTypeProviderComponent, + >>::Delegate: TypesTypeProvider<__Context__>, + { + type Types = <<__Provider__ as DelegateComponent< + TypesTypeProviderComponent, + >>::Delegate as TypesTypeProvider<__Context__>>::Types; + } + pub struct TypesTypeProviderComponent; + impl<__Context__> TypesTypeProvider<__Context__> for UseContext + where + __Context__: HasTypes, + { + type Types = <__Context__ as HasTypes>::Types; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasTypes, + {} + impl<__Context__, __Components__, __Path__> TypesTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: TypesTypeProvider<__Context__>, + { + type Types = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as TypesTypeProvider<__Context__>>::Types; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + TypesTypeProvider<__Context__>, + {} + impl TypesTypeProvider<__Context__> for UseType + where + Types:, + { + type Types = Types; + } + impl IsProviderFor + for UseType + where + Types:, + {} + impl<__Provider__, Types, __Context__> TypesTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, TypesTypeProviderComponent, Type = Types>, + Types:, + { + type Types = Types; + } + impl< + __Provider__, + Types, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, TypesTypeProviderComponent, Type = Types>, + Types:, + {} + ") + } } -#[cgp_fn] -#[use_type(HasTypes::Types, @Types::HasScalarType::Scalar)] -#[extend_where(Types: HasScalarType)] -pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar -where - Scalar: Mul + Copy, -{ - let res: Scalar = width * height; - res +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasTypes::Types, @Types::HasScalarType::Scalar)] + #[extend_where(Types: HasScalarType)] + pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar + where + Scalar: Mul + Copy, + { + let res: Scalar = width * height; + res + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasTypes + where + ::Types: HasScalarType, + { + fn rectangle_area(&self) -> <::Types as HasScalarType>::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + <::Types as HasScalarType>::Scalar: Mul< + Output = <::Types as HasScalarType>::Scalar, + > + Copy, + ::Types: HasScalarType, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <::Types as HasScalarType>::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = <::Types as HasScalarType>::Scalar, + >, + Self: HasTypes, + ::Types: HasScalarType, + { + fn rectangle_area(&self) -> <::Types as HasScalarType>::Scalar { + let width: <::Types as HasScalarType>::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: <::Types as HasScalarType>::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + let res: <::Types as HasScalarType>::Scalar = width * height; + res + } + } + ") + } } pub struct MyTypes; diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/type_equality.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/type_equality.rs index 8da2b1a3..96cbf81b 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/type_equality.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/type_equality.rs @@ -1,17 +1,176 @@ use std::fmt::Display; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_fn] -#[use_type(HasScalarType::{Scalar = f64})] -pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar { - let res: f64 = width * height; - res +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasScalarType::{Scalar = f64})] + pub fn rectangle_area(&self, #[implicit] width: Scalar, #[implicit] height: Scalar) -> Scalar { + let res: f64 = width * height; + res + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasScalarType { + fn rectangle_area(&self) -> ::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = ::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = ::Scalar, + >, + Self: HasScalarType, + { + fn rectangle_area(&self) -> ::Scalar { + let width: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + let res: f64 = width * height; + res + } + } + ") + } } pub trait HasFooType { @@ -24,27 +183,109 @@ pub trait HasBarType { type Bar: Display; } -#[cgp_fn] -#[use_type(HasFooType::Foo)] -pub fn do_foo(&self) -> Foo { - todo!() +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasFooType::Foo)] + pub fn do_foo(&self) -> Foo { + todo!() + } + + expand_do_foo(output) { + insta::assert_snapshot!(output, @" + pub trait DoFoo: HasFooType { + fn do_foo(&self) -> ::Foo; + } + impl<__Context__> DoFoo for __Context__ + where + Self: HasFooType, + { + fn do_foo(&self) -> ::Foo { + todo!() + } + } + ") + } } -#[cgp_fn] -#[use_type(HasBarType::Bar)] -pub fn do_bar(&self) -> Bar { - todo!() +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasBarType::Bar)] + pub fn do_bar(&self) -> Bar { + todo!() + } + + expand_do_bar(output) { + insta::assert_snapshot!(output, @" + pub trait DoBar: HasBarType { + fn do_bar(&self) -> ::Bar; + } + impl<__Context__> DoBar for __Context__ + where + Self: HasBarType, + { + fn do_bar(&self) -> ::Bar { + todo!() + } + } + ") + } } -#[cgp_fn] -#[use_type(HasBarType::{Bar as Baz = Foo}, HasFooType::Foo)] -#[uses(DoFoo, DoBar)] -fn return_foo_or_bar(&self, flag: bool, #[implicit] foo: &Foo, #[implicit] bar: &Baz) -> Foo { - if flag { - let res: Foo = self.do_foo(); - if &res < foo { res } else { foo.clone() } - } else { - let res: Baz = self.do_bar(); - if &res < bar { res } else { bar.clone() } +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasBarType::{Bar as Baz = Foo}, HasFooType::Foo)] + #[uses(DoFoo, DoBar)] + fn return_foo_or_bar(&self, flag: bool, #[implicit] foo: &Foo, #[implicit] bar: &Baz) -> Foo { + if flag { + let res: Foo = self.do_foo(); + if &res < foo { res } else { foo.clone() } + } else { + let res: Baz = self.do_bar(); + if &res < bar { res } else { bar.clone() } + } + } + + expand_return_foo_or_bar(output) { + insta::assert_snapshot!(output, @" + trait ReturnFooOrBar: HasBarType + HasFooType { + fn return_foo_or_bar(&self, flag: bool) -> ::Foo; + } + impl<__Context__> ReturnFooOrBar for __Context__ + where + Self: DoFoo + DoBar, + Self: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = ::Foo, + > + + HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = ::Bar, + >, + Self: HasBarType::Foo>, + Self: HasFooType, + { + fn return_foo_or_bar(&self, flag: bool) -> ::Foo { + let foo: &::Foo = self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ); + let bar: &::Bar = self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ); + if flag { + let res: ::Foo = self.do_foo(); + if &res < foo { res } else { foo.clone() } + } else { + let res: ::Bar = self.do_bar(); + if &res < bar { res } else { bar.clone() } + } + } + } + ") } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_provider.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_provider.rs index b6f32b2f..e44eaaff 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_provider.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_provider.rs @@ -1,21 +1,188 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_component, snapshot_cgp_fn, snapshot_cgp_impl}; -#[cgp_component(AreaCalculator)] -pub trait CanCalculateArea { - fn area(&self) -> f64; +snapshot_cgp_component! { + #[cgp_component(AreaCalculator)] + pub trait CanCalculateArea { + fn area(&self) -> f64; + } + + expand_can_calculate_area(output) { + insta::assert_snapshot!(output, @" + pub trait CanCalculateArea { + fn area(&self) -> f64; + } + impl<__Context__> CanCalculateArea for __Context__ + where + __Context__: AreaCalculator<__Context__>, + { + fn area(&self) -> f64 { + __Context__::area(self) + } + } + pub trait AreaCalculator< + __Context__, + >: IsProviderFor { + fn area(__context__: &__Context__) -> f64; + } + impl<__Provider__, __Context__> AreaCalculator<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + AreaCalculatorComponent, + >>::Delegate: AreaCalculator<__Context__>, + { + fn area(__context__: &__Context__) -> f64 { + <__Provider__ as DelegateComponent< + AreaCalculatorComponent, + >>::Delegate::area(__context__) + } + } + pub struct AreaCalculatorComponent; + impl<__Context__> AreaCalculator<__Context__> for UseContext + where + __Context__: CanCalculateArea, + { + fn area(__context__: &__Context__) -> f64 { + __Context__::area(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: CanCalculateArea, + {} + impl<__Context__, __Components__, __Path__> AreaCalculator<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: AreaCalculator<__Context__>, + { + fn area(__context__: &__Context__) -> f64 { + <__Components__ as DelegateComponent<__Path__>>::Delegate::area(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + AreaCalculator<__Context__>, + {} + ") + } } -#[cgp_impl(new RectangleAreaCalculator)] -impl AreaCalculator { - fn area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_impl! { + #[cgp_impl(new RectangleAreaCalculator)] + impl AreaCalculator { + fn area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + } + + expand_rectangle_area_calculator(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> AreaCalculator<__Context__> for RectangleAreaCalculator + where + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn area(__context__: &__Context__) -> f64 { + let width: f64 = __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + impl<__Context__> IsProviderFor + for RectangleAreaCalculator + where + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + {} + pub struct RectangleAreaCalculator; + ") } } -#[cgp_fn] -#[use_provider(RectangleAreaCalculator: AreaCalculator)] -fn rectangle_area(&self) -> f64 { - RectangleAreaCalculator::area(self) +snapshot_cgp_fn! { + #[cgp_fn] + #[use_provider(RectangleAreaCalculator: AreaCalculator)] + fn rectangle_area(&self) -> f64 { + RectangleAreaCalculator::area(self) + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + trait RectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> RectangleArea for __Context__ + where + RectangleAreaCalculator: AreaCalculator, + { + fn rectangle_area(&self) -> f64 { + RectangleAreaCalculator::area(self) + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type.rs index 95ccfec5..04b4abee 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type.rs @@ -2,20 +2,178 @@ use core::f64; use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar: Mul + Copy; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar: Mul + Copy; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Mul + Copy; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar: Mul + Copy; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar: Mul + Copy, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar: Mul + Copy, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Mul + Copy, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Mul + Copy, + {} + ") + } } -#[cgp_fn] -#[extend(HasScalarType)] -pub fn rectangle_area( - &self, - #[implicit] width: Self::Scalar, - #[implicit] height: Self::Scalar, -) -> Self::Scalar { - width * height +snapshot_cgp_fn! { + #[cgp_fn] + #[extend(HasScalarType)] + pub fn rectangle_area( + &self, + #[implicit] width: Self::Scalar, + #[implicit] height: Self::Scalar, + ) -> Self::Scalar { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasScalarType { + fn rectangle_area(&self) -> Self::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasScalarType, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = Self::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = Self::Scalar, + >, + { + fn rectangle_area(&self) -> Self::Scalar { + let width: Self::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: Self::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type_alias.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type_alias.rs index a22706e3..8e85f7c5 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type_alias.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/use_type_alias.rs @@ -1,18 +1,179 @@ use std::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } -#[cgp_fn] -#[use_type(HasScalarType::{Scalar as S})] -pub fn rectangle_area(&self, #[implicit] width: S, #[implicit] height: S) -> S -where - S: Mul + Copy, -{ - let res: S = width * height; - res +snapshot_cgp_fn! { + #[cgp_fn] + #[use_type(HasScalarType::{Scalar as S})] + pub fn rectangle_area(&self, #[implicit] width: S, #[implicit] height: S) -> S + where + S: Mul + Copy, + { + let res: S = width * height; + res + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea: HasScalarType { + fn rectangle_area(&self) -> ::Scalar; + } + impl<__Context__> RectangleArea for __Context__ + where + ::Scalar: Mul::Scalar> + + Copy, + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = ::Scalar, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = ::Scalar, + >, + Self: HasScalarType, + { + fn rectangle_area(&self) -> ::Scalar { + let width: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: ::Scalar = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + let res: ::Scalar = width * height; + res + } + } + ") + } } diff --git a/crates/tests/cgp-tests/tests/cgp_fn_tests/uses.rs b/crates/tests/cgp-tests/tests/cgp_fn_tests/uses.rs index a267732b..1daf1fbd 100644 --- a/crates/tests/cgp-tests/tests/cgp_fn_tests/uses.rs +++ b/crates/tests/cgp-tests/tests/cgp_fn_tests/uses.rs @@ -1,14 +1,155 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_fn; -#[cgp_fn] -pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn rectangle_area(&self) -> f64 { + let width: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } -#[cgp_fn] -#[uses(RectangleArea)] -pub fn scaled_rectangle_area(&self, #[implicit] scale_factor: f64) -> f64 { - self.rectangle_area() * scale_factor * scale_factor +snapshot_cgp_fn! { + #[cgp_fn] + #[uses(RectangleArea)] + pub fn scaled_rectangle_area(&self, #[implicit] scale_factor: f64) -> f64 { + self.rectangle_area() * scale_factor * scale_factor + } + + expand_scaled_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait ScaledRectangleArea { + fn scaled_rectangle_area(&self) -> f64; + } + impl<__Context__> ScaledRectangleArea for __Context__ + where + Self: RectangleArea, + Self: HasField< + Symbol< + 12, + Chars< + 's', + Chars< + 'c', + Chars< + 'a', + Chars< + 'l', + Chars< + 'e', + Chars< + '_', + Chars< + 'f', + Chars< + 'a', + Chars<'c', Chars<'t', Chars<'o', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + >, + >, + >, + >, + Value = f64, + >, + { + fn scaled_rectangle_area(&self) -> f64 { + let scale_factor: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 12, + Chars< + 's', + Chars< + 'c', + Chars< + 'a', + Chars< + 'l', + Chars< + 'e', + Chars< + '_', + Chars< + 'f', + Chars< + 'a', + Chars<'c', Chars<'t', Chars<'o', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + >, + >, + >, + >, + >, + ) + .clone(); + self.rectangle_area() * scale_factor * scale_factor + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/component_tests/abstract_types/basic.rs b/crates/tests/cgp-tests/tests/component_tests/abstract_types/basic.rs index e7c28fa2..3be3ab9c 100644 --- a/crates/tests/cgp-tests/tests/component_tests/abstract_types/basic.rs +++ b/crates/tests/cgp-tests/tests/component_tests/abstract_types/basic.rs @@ -3,10 +3,110 @@ use std::ops::Mul; use cgp::core::error::ErrorTypeProviderComponent; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_type, snapshot_delegate_and_check_components}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } #[cgp_component(AreaCalculator)] @@ -32,13 +132,59 @@ pub struct Rectangle { pub height: f64, } -delegate_and_check_components! { - Rectangle { - ErrorTypeProviderComponent: - UseType, - ScalarTypeProviderComponent: - UseType, - AreaCalculatorComponent: - RectangleArea, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Rectangle { + ErrorTypeProviderComponent: + UseType, + ScalarTypeProviderComponent: + UseType, + AreaCalculatorComponent: + RectangleArea, + } + } + + expand_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Rectangle { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + UseType< + Infallible, + >: IsProviderFor, + {} + impl DelegateComponent for Rectangle { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + UseType: IsProviderFor, + {} + impl DelegateComponent for Rectangle { + type Delegate = RectangleArea; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + RectangleArea: IsProviderFor, + {} + trait __CanUseRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseRectangle for Rectangle {} + impl __CanUseRectangle for Rectangle {} + impl __CanUseRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/abstract_types/extend.rs b/crates/tests/cgp-tests/tests/component_tests/abstract_types/extend.rs index 33f00d79..ecd29bd3 100644 --- a/crates/tests/cgp-tests/tests/component_tests/abstract_types/extend.rs +++ b/crates/tests/cgp-tests/tests/component_tests/abstract_types/extend.rs @@ -3,10 +3,110 @@ use std::ops::Mul; use cgp::core::error::ErrorTypeProviderComponent; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_type, snapshot_delegate_and_check_components}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } #[cgp_component(AreaCalculator)] @@ -36,13 +136,59 @@ pub struct Rectangle { pub height: f64, } -delegate_and_check_components! { - Rectangle { - ErrorTypeProviderComponent: - UseType, - ScalarTypeProviderComponent: - UseType, - AreaCalculatorComponent: - RectangleArea, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Rectangle { + ErrorTypeProviderComponent: + UseType, + ScalarTypeProviderComponent: + UseType, + AreaCalculatorComponent: + RectangleArea, + } + } + + expand_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Rectangle { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + UseType< + Infallible, + >: IsProviderFor, + {} + impl DelegateComponent for Rectangle { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + UseType: IsProviderFor, + {} + impl DelegateComponent for Rectangle { + type Delegate = RectangleArea; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + RectangleArea: IsProviderFor, + {} + trait __CanUseRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseRectangle for Rectangle {} + impl __CanUseRectangle for Rectangle {} + impl __CanUseRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/abstract_types/foreign.rs b/crates/tests/cgp-tests/tests/component_tests/abstract_types/foreign.rs index 2818e32d..94c983d1 100644 --- a/crates/tests/cgp-tests/tests/component_tests/abstract_types/foreign.rs +++ b/crates/tests/cgp-tests/tests/component_tests/abstract_types/foreign.rs @@ -3,10 +3,110 @@ use std::ops::Mul; use cgp::core::error::ErrorTypeProviderComponent; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_type, snapshot_check_components}; -#[cgp_type] -pub trait HasScalarType { - type Scalar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar:, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar:, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar:, + {} + ") + } } #[cgp_component(AreaCalculator)] @@ -47,8 +147,20 @@ delegate_components! { } } -check_components! { - Rectangle { - AreaCalculatorComponent: Types, +snapshot_check_components! { + check_components! { + Rectangle { + AreaCalculatorComponent: Types, + } + } + + expand_check_rectangle(output) { + insta::assert_snapshot!(output, @" + trait __CheckRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/abstract_types/self_referential.rs b/crates/tests/cgp-tests/tests/component_tests/abstract_types/self_referential.rs index ee96d510..8c0dba27 100644 --- a/crates/tests/cgp-tests/tests/component_tests/abstract_types/self_referential.rs +++ b/crates/tests/cgp-tests/tests/component_tests/abstract_types/self_referential.rs @@ -1,10 +1,110 @@ use core::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_type, snapshot_check_components}; -#[cgp_type] -pub trait HasScalarType { - type Scalar: Mul + Clone; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar: Mul + Clone; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Mul + Clone; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar: Mul + Clone; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar: Mul + Clone, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar: Mul + Clone, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Mul + Clone, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Mul + Clone, + {} + ") + } } pub struct App; @@ -16,8 +116,20 @@ delegate_components! { } } -check_components! { - App { - ScalarTypeProviderComponent, +snapshot_check_components! { + check_components! { + App { + ScalarTypeProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_component/constant.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_component/constant.rs index 1f8e018c..85d6117a 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_component/constant.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_component/constant.rs @@ -1,6 +1,7 @@ -use cgp::prelude::*; +mod basic_const { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_provider, snapshot_delegate_and_check_components}; -pub fn test_component_with_const() { #[cgp_component(ConstantGetter)] pub trait HasConstant { const CONSTANT: u64; @@ -8,26 +9,168 @@ pub fn test_component_with_const() { pub struct UseConstant; - #[cgp_provider] - impl ConstantGetter for UseConstant { - const CONSTANT: u64 = CONSTANT; + snapshot_cgp_provider! { + #[cgp_provider] + impl ConstantGetter for UseConstant { + const CONSTANT: u64 = CONSTANT; + } + + expand_use_constant(output) { + insta::assert_snapshot!(output, @" + impl ConstantGetter for UseConstant { + const CONSTANT: u64 = CONSTANT; + } + impl IsProviderFor + for UseConstant {} + ") + } } pub struct MyContext; - delegate_and_check_components! { - MyContext { - ConstantGetterComponent: UseConstant<42>, + snapshot_delegate_and_check_components! { + delegate_and_check_components! { + MyContext { + ConstantGetterComponent: UseConstant<42>, + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for MyContext { + type Delegate = UseConstant<42>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseConstant<42>: IsProviderFor, + {} + trait __CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseMyContext for MyContext {} + ") } } +} + +pub fn test_component_with_const() { + use basic_const::{HasConstant, MyContext}; assert_eq!(::CONSTANT, 42); } -pub fn test_component_with_generic_const() { - #[cgp_type] - pub trait HasUnitType { - type Unit; +mod generic_const { + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_provider, snapshot_cgp_type, snapshot_check_components, + }; + + snapshot_cgp_type! { + #[cgp_type] + pub trait HasUnitType { + type Unit; + } + + expand_has_unit_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasUnitType { + type Unit; + } + impl<__Context__> HasUnitType for __Context__ + where + __Context__: UnitTypeProvider<__Context__>, + { + type Unit = <__Context__ as UnitTypeProvider<__Context__>>::Unit; + } + pub trait UnitTypeProvider< + __Context__, + >: IsProviderFor { + type Unit; + } + impl<__Provider__, __Context__> UnitTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + UnitTypeProviderComponent, + >>::Delegate: UnitTypeProvider<__Context__>, + { + type Unit = <<__Provider__ as DelegateComponent< + UnitTypeProviderComponent, + >>::Delegate as UnitTypeProvider<__Context__>>::Unit; + } + pub struct UnitTypeProviderComponent; + impl<__Context__> UnitTypeProvider<__Context__> for UseContext + where + __Context__: HasUnitType, + { + type Unit = <__Context__ as HasUnitType>::Unit; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasUnitType, + {} + impl<__Context__, __Components__, __Path__> UnitTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: UnitTypeProvider<__Context__>, + { + type Unit = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as UnitTypeProvider<__Context__>>::Unit; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + UnitTypeProvider<__Context__>, + {} + impl UnitTypeProvider<__Context__> for UseType + where + Unit:, + { + type Unit = Unit; + } + impl IsProviderFor + for UseType + where + Unit:, + {} + impl<__Provider__, Unit, __Context__> UnitTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, UnitTypeProviderComponent, Type = Unit>, + Unit:, + { + type Unit = Unit; + } + impl< + __Provider__, + Unit, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, UnitTypeProviderComponent, Type = Unit>, + Unit:, + {} + ") + } } #[cgp_component(ConstantGetter)] @@ -37,12 +180,30 @@ pub fn test_component_with_generic_const() { pub struct UseConstant; - #[cgp_provider] - impl ConstantGetter for UseConstant - where - Context: HasUnitType, - { - const CONSTANT: u64 = CONSTANT; + snapshot_cgp_provider! { + #[cgp_provider] + impl ConstantGetter for UseConstant + where + Context: HasUnitType, + { + const CONSTANT: u64 = CONSTANT; + } + + expand_use_constant(output) { + insta::assert_snapshot!(output, @" + impl ConstantGetter for UseConstant + where + Context: HasUnitType, + { + const CONSTANT: u64 = CONSTANT; + } + impl IsProviderFor + for UseConstant + where + Context: HasUnitType, + {} + ") + } } pub struct MyContext; @@ -54,11 +215,27 @@ pub fn test_component_with_generic_const() { } } - check_components! { - MyContext { - ConstantGetterComponent, + snapshot_check_components! { + check_components! { + MyContext { + ConstantGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + ") } } +} + +pub fn test_component_with_generic_const() { + use generic_const::{HasConstant, MyContext}; assert_eq!(::CONSTANT, 42); } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_component/default_impl.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_component/default_impl.rs index 0410f390..971edfe2 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_component/default_impl.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_component/default_impl.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_component; #[cgp_getter] pub trait HasName { @@ -7,10 +8,94 @@ pub trait HasName { } } -#[cgp_component(Greeter)] -pub trait CanGreet: HasName { - fn greet(&self) -> String { - format!("Hello, {}!", self.name()) +snapshot_cgp_component! { + #[cgp_component(Greeter)] + pub trait CanGreet: HasName { + fn greet(&self) -> String { + format!("Hello, {}!", self.name()) + } + } + + expand_can_greet(output) { + insta::assert_snapshot!(output, @r#" + pub trait CanGreet: HasName { + fn greet(&self) -> String { + format!("Hello, {}!", self.name()) + } + } + impl<__Context__> CanGreet for __Context__ + where + __Context__: HasName, + __Context__: Greeter<__Context__>, + { + fn greet(&self) -> String { + __Context__::greet(self) + } + } + pub trait Greeter<__Context__>: IsProviderFor + where + __Context__: HasName, + { + fn greet(__context__: &__Context__) -> String { + format!("Hello, {}!", __context__.name()) + } + } + impl<__Provider__, __Context__> Greeter<__Context__> for __Provider__ + where + __Context__: HasName, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + GreeterComponent, + >>::Delegate: Greeter<__Context__>, + { + fn greet(__context__: &__Context__) -> String { + <__Provider__ as DelegateComponent< + GreeterComponent, + >>::Delegate::greet(__context__) + } + } + pub struct GreeterComponent; + impl<__Context__> Greeter<__Context__> for UseContext + where + __Context__: HasName, + __Context__: CanGreet, + { + fn greet(__context__: &__Context__) -> String { + __Context__::greet(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasName, + __Context__: CanGreet, + {} + impl<__Context__, __Components__, __Path__> Greeter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasName, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: Greeter<__Context__>, + { + fn greet(__context__: &__Context__) -> String { + <__Components__ as DelegateComponent<__Path__>>::Delegate::greet(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasName, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + Greeter<__Context__>, + {} + "#) } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_component/lifetime.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_component/lifetime.rs index af0e4439..6806116e 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_component/lifetime.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_component/lifetime.rs @@ -1,17 +1,140 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_provider, snapshot_check_components, +}; -#[cgp_component(ReferenceGetter)] -pub trait HasReference<'a, T: 'a + ?Sized> { - fn get_reference(&self) -> &'a T; +snapshot_cgp_component! { + #[cgp_component(ReferenceGetter)] + pub trait HasReference<'a, T: 'a + ?Sized> { + fn get_reference(&self) -> &'a T; + } + + expand_can_greet(output) { + insta::assert_snapshot!(output, @" + pub trait HasReference<'a, T: 'a + ?Sized> { + fn get_reference(&self) -> &'a T; + } + impl<'a, __Context__, T: 'a + ?Sized> HasReference<'a, T> for __Context__ + where + __Context__: ReferenceGetter<'a, __Context__, T>, + { + fn get_reference(&self) -> &'a T { + __Context__::get_reference(self) + } + } + pub trait ReferenceGetter< + 'a, + __Context__, + T: 'a + ?Sized, + >: IsProviderFor, T)> { + fn get_reference(__context__: &__Context__) -> &'a T; + } + impl<'a, __Provider__, __Context__, T: 'a + ?Sized> ReferenceGetter<'a, __Context__, T> + for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, T)>, + <__Provider__ as DelegateComponent< + ReferenceGetterComponent, + >>::Delegate: ReferenceGetter<'a, __Context__, T>, + { + fn get_reference(__context__: &__Context__) -> &'a T { + <__Provider__ as DelegateComponent< + ReferenceGetterComponent, + >>::Delegate::get_reference(__context__) + } + } + pub struct ReferenceGetterComponent; + impl<'a, __Context__, T: 'a + ?Sized> ReferenceGetter<'a, __Context__, T> for UseContext + where + __Context__: HasReference<'a, T>, + { + fn get_reference(__context__: &__Context__) -> &'a T { + __Context__::get_reference(__context__) + } + } + impl< + 'a, + __Context__, + T: 'a + ?Sized, + > IsProviderFor, T)> for UseContext + where + __Context__: HasReference<'a, T>, + {} + impl< + 'a, + __Context__, + T: 'a + ?Sized, + __Components__, + __Path__, + > ReferenceGetter<'a, __Context__, T> for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: ReferenceGetter<'a, __Context__, T>, + { + fn get_reference(__context__: &__Context__) -> &'a T { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::get_reference(__context__) + } + } + impl< + 'a, + __Context__, + T: 'a + ?Sized, + __Components__, + __Path__, + > IsProviderFor, T)> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: ReferenceGetter<'a, __Context__, T>, + {} + ") + } } -#[cgp_provider] -impl<'a, Context, Tag, T: 'a + ?Sized> ReferenceGetter<'a, Context, T> for UseField -where - Context: HasField, -{ - fn get_reference(context: &Context) -> &'a T { - context.get_field(PhantomData) +snapshot_cgp_provider! { + #[cgp_provider] + impl<'a, Context, Tag, T: 'a + ?Sized> ReferenceGetter<'a, Context, T> for UseField + where + Context: HasField, + { + fn get_reference(context: &Context) -> &'a T { + context.get_field(PhantomData) + } + } + + expand_use_field_reference_getter(output) { + insta::assert_snapshot!(output, @" + impl<'a, Context, Tag, T: 'a + ?Sized> ReferenceGetter<'a, Context, T> for UseField + where + Context: HasField, + { + fn get_reference(context: &Context) -> &'a T { + context.get_field(PhantomData) + } + } + impl< + 'a, + Context, + Tag, + T: 'a + ?Sized, + > IsProviderFor, T)> for UseField + where + Context: HasField, + {} + ") } } @@ -33,9 +156,21 @@ delegate_components! { } } -check_components! { - <'a> App<'a> { - ReferenceGetterComponent: - (Life<'a>, str), +snapshot_check_components! { + check_components! { + <'a> App<'a> { + ReferenceGetterComponent: + (Life<'a>, str), + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl<'a> __CheckApp, str)> for App<'a> {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_component/sized.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_component/sized.rs index e347d241..7db71c9a 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_component/sized.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_component/sized.rs @@ -1,8 +1,120 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_type; -#[cgp_type(ProvideFooType)] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type(ProvideFooType)] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__, T: ?Sized> HasFooType for __Context__ + where + __Context__: ProvideFooType<__Context__, T>, + { + type Foo = <__Context__ as ProvideFooType<__Context__, T>>::Foo; + } + pub trait ProvideFooType< + __Context__, + T: ?Sized, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__, T: ?Sized> ProvideFooType<__Context__, T> + for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ProvideFooTypeComponent, + >>::Delegate: ProvideFooType<__Context__, T>, + { + type Foo = <<__Provider__ as DelegateComponent< + ProvideFooTypeComponent, + >>::Delegate as ProvideFooType<__Context__, T>>::Foo; + } + pub struct ProvideFooTypeComponent; + impl<__Context__, T: ?Sized> ProvideFooType<__Context__, T> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__, T: ?Sized> IsProviderFor + for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, T: ?Sized, __Components__, __Path__> ProvideFooType<__Context__, T> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: ProvideFooType<__Context__, T>, + { + type Foo = <<__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate as ProvideFooType<__Context__, T>>::Foo; + } + impl< + __Context__, + T: ?Sized, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + ProvideFooType<__Context__, T>, + {} + impl ProvideFooType<__Context__, T> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl< + Foo, + __Context__, + T: ?Sized, + > IsProviderFor for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__, T: ?Sized> ProvideFooType<__Context__, T> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ProvideFooTypeComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + T: ?Sized, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ProvideFooTypeComponent, Type = Foo>, + Foo:, + {} + ") + } } #[cgp_getter] diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/basic.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/basic.rs index b4cfc13f..b2ee00ef 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/basic.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/basic.rs @@ -1,19 +1,134 @@ -use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_auto_getter, snapshot_cgp_component, snapshot_cgp_impl}; -#[cgp_component(FooProvider)] -pub trait CanDoFoo { - fn foo(&self, value: u32) -> String; +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait CanDoFoo { + fn foo(&self, value: u32) -> String; + } + + expand_foo_component(output) { + insta::assert_snapshot!(output, @" + pub trait CanDoFoo { + fn foo(&self, value: u32) -> String; + } + impl<__Context__> CanDoFoo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self, value: u32) -> String { + __Context__::foo(self, value) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__, value: u32) -> String; + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__, value: u32) -> String { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__, value) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: CanDoFoo, + { + fn foo(__context__: &__Context__, value: u32) -> String { + __Context__::foo(__context__, value) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: CanDoFoo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__, value: u32) -> String { + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate::foo(__context__, value) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + ") + } } -#[cgp_auto_getter] -pub trait HasName { - fn name(&self) -> &str; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasName { + fn name(&self) -> &str; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName { + fn name(&self) -> &str; + } + impl<__Context__> HasName for __Context__ + where + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = String, + >, + { + fn name(&self) -> &str { + self.get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .as_str() + } + } + ") + } } -#[cgp_impl(new ValueToString)] -impl FooProvider for Context { - fn foo(&self, value: u32) -> String { - value.to_string() +snapshot_cgp_impl! { + #[cgp_impl(new ValueToString)] + impl FooProvider for Context { + fn foo(&self, value: u32) -> String { + value.to_string() + } + } + + expand_value_to_string(output) { + insta::assert_snapshot!(output, @" + impl FooProvider for ValueToString { + fn foo(__context__: &Context, value: u32) -> String { + value.to_string() + } + } + impl IsProviderFor for ValueToString {} + pub struct ValueToString; + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/basic.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/basic.rs index 99d88075..88594614 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/basic.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/basic.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_and_check_components; #[cgp_component(AreaCalculator)] pub trait CanCalculateArea { @@ -18,9 +19,31 @@ pub struct Rectangle { pub height: f64, } -delegate_and_check_components! { - Rectangle { - AreaCalculatorComponent: - RectangleArea, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Rectangle { + AreaCalculatorComponent: + RectangleArea, + } + } + + expand_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Rectangle { + type Delegate = RectangleArea; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + RectangleArea: IsProviderFor, + {} + trait __CanUseRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs index 5032ca21..5e4a2d5b 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/generics.rs @@ -1,6 +1,7 @@ use core::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_and_check_components; #[cgp_component(AreaCalculator)] pub trait CanCalculateArea { @@ -23,10 +24,32 @@ pub struct Rectangle { pub height: f64, } -delegate_and_check_components! { - Rectangle { - #[check_params(f64)] - AreaCalculatorComponent: - RectangleArea, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Rectangle { + #[check_params(f64)] + AreaCalculatorComponent: + RectangleArea, + } + } + + expand_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Rectangle { + type Delegate = RectangleArea; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + RectangleArea: IsProviderFor, + {} + trait __CanUseRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/import.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/import.rs index c946e12a..b8fe907f 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/import.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/implicit_args/import.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_fn, snapshot_delegate_and_check_components}; #[cgp_component(AreaCalculator)] pub trait CanCalculateArea { @@ -13,9 +14,66 @@ impl AreaCalculator { } } -#[cgp_fn] -pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn rectangle_area(&self) -> f64 { + let width: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } #[derive(HasField)] @@ -24,9 +82,35 @@ pub struct Rectangle { pub height: f64, } -delegate_and_check_components! { - Rectangle { - AreaCalculatorComponent: - RectangleAreaCalculator, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + Rectangle { + AreaCalculatorComponent: + RectangleAreaCalculator, + } + } + + expand_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Rectangle { + type Delegate = RectangleAreaCalculator; + } + impl< + __Context__, + __Params__, + > IsProviderFor for Rectangle + where + RectangleAreaCalculator: IsProviderFor< + AreaCalculatorComponent, + __Context__, + __Params__, + >, + {} + trait __CanUseRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseRectangle for Rectangle {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/shape.rs b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/shape.rs index 337f6bd7..2a9fc0cd 100644 --- a/crates/tests/cgp-tests/tests/component_tests/cgp_impl/shape.rs +++ b/crates/tests/cgp-tests/tests/component_tests/cgp_impl/shape.rs @@ -1,15 +1,115 @@ use core::f64::consts::PI; use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_fn, snapshot_check_components, snapshot_delegate_and_check_components, +}; -#[cgp_fn] -pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { - width * height +snapshot_cgp_fn! { + #[cgp_fn] + pub fn rectangle_area(&self, #[implicit] width: f64, #[implicit] height: f64) -> f64 { + width * height + } + + expand_rectangle_area(output) { + insta::assert_snapshot!(output, @" + pub trait RectangleArea { + fn rectangle_area(&self) -> f64; + } + impl<__Context__> RectangleArea for __Context__ + where + Self: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = f64, + > + + HasField< + Symbol< + 6, + Chars< + 'h', + Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>, + >, + >, + Value = f64, + >, + { + fn rectangle_area(&self) -> f64 { + let width: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone(); + let height: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + width * height + } + } + ") + } } -#[cgp_fn] -pub fn circle_area(&self, #[implicit] radius: f64) -> f64 { - PI * radius * radius +snapshot_cgp_fn! { + #[cgp_fn] + pub fn circle_area(&self, #[implicit] radius: f64) -> f64 { + PI * radius * radius + } + + expand_circle_area(output) { + insta::assert_snapshot!(output, @" + pub trait CircleArea { + fn circle_area(&self) -> f64; + } + impl<__Context__> CircleArea for __Context__ + where + Self: HasField< + Symbol< + 6, + Chars<'r', Chars<'a', Chars<'d', Chars<'i', Chars<'u', Chars<'s', Nil>>>>>>, + >, + Value = f64, + >, + { + fn circle_area(&self) -> f64 { + let radius: f64 = self + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'r', + Chars< + 'a', + Chars<'d', Chars<'i', Chars<'u', Chars<'s', Nil>>>>, + >, + >, + >, + >, + ) + .clone(); + PI * radius * radius + } + } + ") + } } #[cgp_component(AreaCalculator)] @@ -100,10 +200,36 @@ pub struct PlainRectangle { pub height: f64, } -delegate_and_check_components! { - PlainRectangle { - AreaCalculatorComponent: - RectangleAreaCalculator, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + PlainRectangle { + AreaCalculatorComponent: + RectangleAreaCalculator, + } + } + + expand_plain_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for PlainRectangle { + type Delegate = RectangleAreaCalculator; + } + impl< + __Context__, + __Params__, + > IsProviderFor for PlainRectangle + where + RectangleAreaCalculator: IsProviderFor< + AreaCalculatorComponent, + __Context__, + __Params__, + >, + {} + trait __CanUsePlainRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUsePlainRectangle for PlainRectangle {} + ") } } @@ -114,10 +240,34 @@ pub struct ScaledRectangle { pub height: f64, } -delegate_and_check_components! { - ScaledRectangle { - AreaCalculatorComponent: - ScaledAreaCalculator, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + ScaledRectangle { + AreaCalculatorComponent: + ScaledAreaCalculator, + } + } + + expand_scaled_rectangle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for ScaledRectangle { + type Delegate = ScaledAreaCalculator; + } + impl< + __Context__, + __Params__, + > IsProviderFor for ScaledRectangle + where + ScaledAreaCalculator< + RectangleAreaCalculator, + >: IsProviderFor, + {} + trait __CanUseScaledRectangle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseScaledRectangle for ScaledRectangle {} + ") } } @@ -126,10 +276,36 @@ pub struct PlainCircle { pub radius: f64, } -delegate_and_check_components! { - PlainCircle { - AreaCalculatorComponent: - CircleAreaCalculator, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + PlainCircle { + AreaCalculatorComponent: + CircleAreaCalculator, + } + } + + expand_plain_circle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for PlainCircle { + type Delegate = CircleAreaCalculator; + } + impl< + __Context__, + __Params__, + > IsProviderFor for PlainCircle + where + CircleAreaCalculator: IsProviderFor< + AreaCalculatorComponent, + __Context__, + __Params__, + >, + {} + trait __CanUsePlainCircle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUsePlainCircle for PlainCircle {} + ") } } @@ -139,21 +315,60 @@ pub struct ScaledCircle { pub radius: f64, } -delegate_and_check_components! { - ScaledCircle { - AreaCalculatorComponent: - ScaledAreaCalculator, +snapshot_delegate_and_check_components! { + delegate_and_check_components! { + ScaledCircle { + AreaCalculatorComponent: + ScaledAreaCalculator, + } + } + + expand_scaled_circle(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for ScaledCircle { + type Delegate = ScaledAreaCalculator; + } + impl< + __Context__, + __Params__, + > IsProviderFor for ScaledCircle + where + ScaledAreaCalculator< + CircleAreaCalculator, + >: IsProviderFor, + {} + trait __CanUseScaledCircle< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CanUseScaledCircle for ScaledCircle {} + ") } } -check_components! { - #[check_trait(CheckScaledRectangleProviders)] - #[check_providers( - RectangleAreaCalculator, - ScaledAreaCalculator, - )] - ScaledRectangle { - AreaCalculatorComponent, +snapshot_check_components! { + check_components! { + #[check_trait(CheckScaledRectangleProviders)] + #[check_providers( + RectangleAreaCalculator, + ScaledAreaCalculator, + )] + ScaledRectangle { + AreaCalculatorComponent, + } + } + + expand_check_scaled_rectangle_providers(output) { + insta::assert_snapshot!(output, @" + trait CheckScaledRectangleProviders< + __Component__, + __Params__: ?Sized, + >: IsProviderFor<__Component__, ScaledRectangle, __Params__> {} + impl CheckScaledRectangleProviders + for RectangleAreaCalculator {} + impl CheckScaledRectangleProviders + for ScaledAreaCalculator {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/delegate_components/direct.rs b/crates/tests/cgp-tests/tests/component_tests/delegate_components/direct.rs index c5017a8b..158ec76c 100644 --- a/crates/tests/cgp-tests/tests/component_tests/delegate_components/direct.rs +++ b/crates/tests/cgp-tests/tests/component_tests/delegate_components/direct.rs @@ -1,18 +1,73 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; -delegate_components! { - new FooComponents { - Index<0>: u64, - Index<1>: String, +snapshot_delegate_components! { + delegate_components! { + new FooComponents { + Index<0>: u64, + Index<1>: String, + } + } + + expand_foo_component(output) { + insta::assert_snapshot!(output, @" + pub struct FooComponents; + impl DelegateComponent> for FooComponents { + type Delegate = u64; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooComponents + where + u64: IsProviderFor, __Context__, __Params__>, + {} + impl DelegateComponent> for FooComponents { + type Delegate = String; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for FooComponents + where + String: IsProviderFor, __Context__, __Params__>, + {} + ") } } -delegate_components! { - new BarComponents { - Index<0>: - FooComponents, - Index<1> -> - FooComponents, +snapshot_delegate_components! { + delegate_components! { + new BarComponents { + Index<0>: + FooComponents, + Index<1> -> + FooComponents, + } + } + + expand_bar_component(output) { + insta::assert_snapshot!(output, @" + pub struct BarComponents; + impl DelegateComponent> for BarComponents { + type Delegate = FooComponents; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for BarComponents + where + FooComponents: IsProviderFor, __Context__, __Params__>, + {} + impl DelegateComponent> for BarComponents + where + FooComponents: DelegateComponent>, + { + type Delegate = >>::Delegate; + } + impl<__Context__, __Params__> IsProviderFor, __Context__, __Params__> + for BarComponents + where + FooComponents: DelegateComponent>, + , + >>::Delegate: IsProviderFor, __Context__, __Params__>, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/component_tests/delegate_components/general.rs b/crates/tests/cgp-tests/tests/component_tests/delegate_components/general.rs index d7035cbc..76cbb9b5 100644 --- a/crates/tests/cgp-tests/tests/component_tests/delegate_components/general.rs +++ b/crates/tests/cgp-tests/tests/component_tests/delegate_components/general.rs @@ -1,11 +1,10 @@ #![allow(unused)] -use core::marker::PhantomData; +mod test_basic_delegate_components { + use cgp::prelude::DelegateComponent; + use cgp_macro_test_util::snapshot_delegate_components; + use insta::assert_snapshot; -use cgp::prelude::*; - -#[test] -fn test_basic_delegate_components() { pub struct FooKey; pub struct FooValue; pub struct BarKey; @@ -14,14 +13,45 @@ fn test_basic_delegate_components() { pub struct Components; - delegate_components! { - Components { - FooKey: FooValue, - [ - BarKey, - BazKey, - ]: - BarValue, + snapshot_delegate_components! { + delegate_components! { + Components { + FooKey: FooValue, + [ + BarKey, + BazKey, + ]: + BarValue, + } + } + + expand_components(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for Components { + type Delegate = FooValue; + } + impl<__Context__, __Params__> IsProviderFor + for Components + where + FooValue: IsProviderFor, + {} + impl DelegateComponent for Components { + type Delegate = BarValue; + } + impl<__Context__, __Params__> IsProviderFor + for Components + where + BarValue: IsProviderFor, + {} + impl DelegateComponent for Components { + type Delegate = BarValue; + } + impl<__Context__, __Params__> IsProviderFor + for Components + where + BarValue: IsProviderFor, + {} + ") } } @@ -35,8 +65,13 @@ fn test_basic_delegate_components() { impl CheckDelegates for Components {} } -#[test] -fn test_generic_delegate_components() { +mod test_generic_delegate_components { + use core::marker::PhantomData; + + use cgp::prelude::DelegateComponent; + use cgp_macro_test_util::snapshot_delegate_components; + use insta::assert_snapshot; + pub struct FooKey(pub PhantomData); pub struct FooValue; pub struct BarKey<'a, T>(pub PhantomData<(&'a (), T)>); @@ -45,15 +80,58 @@ fn test_generic_delegate_components() { pub struct Components; - delegate_components! { - <'a, T1: Clone> - Components { - FooKey: FooValue, - [ - BarKey<'a, T1>, - BazKey, - ]: - BarValue, + snapshot_delegate_components! { + delegate_components! { + <'a, T1: Clone> + Components { + FooKey: FooValue, + [ + BarKey<'a, T1>, + BazKey, + ]: + BarValue, + } + } + expand_components(output) { + insta::assert_snapshot!(output, @" + impl<'a, T1: Clone> DelegateComponent> for Components { + type Delegate = FooValue; + } + impl< + 'a, + T1: Clone, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for Components + where + FooValue: IsProviderFor, __Context__, __Params__>, + {} + impl<'a, T1: Clone> DelegateComponent> for Components { + type Delegate = BarValue; + } + impl< + 'a, + T1: Clone, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for Components + where + BarValue: IsProviderFor, __Context__, __Params__>, + {} + impl<'a, T1: Clone, T2> DelegateComponent> for Components { + type Delegate = BarValue; + } + impl< + 'a, + T1: Clone, + T2, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for Components + where + BarValue: IsProviderFor, __Context__, __Params__>, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/extensible_data_tests/records/basic.rs b/crates/tests/cgp-tests/tests/extensible_data_tests/records/basic.rs index b92f06ff..fa93bbcc 100644 --- a/crates/tests/cgp-tests/tests/extensible_data_tests/records/basic.rs +++ b/crates/tests/cgp-tests/tests/extensible_data_tests/records/basic.rs @@ -6,6 +6,7 @@ use cgp::core::field::impls::CanBuildFrom; use cgp::extra::dispatch::{BuildAndMerge, BuildAndSetField, BuildWithHandlers}; use cgp::extra::handler::{Computer, Producer, ProducerComponent}; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; #[derive(Debug, Eq, PartialEq, CgpData)] pub struct FooBarBaz { @@ -82,9 +83,28 @@ pub fn build_baz() -> bool { pub struct App; -delegate_components! { - App { - ErrorTypeProviderComponent: UseType, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: UseType, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType< + Infallible, + >: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/extensible_data_tests/variants/basic.rs b/crates/tests/cgp-tests/tests/extensible_data_tests/variants/basic.rs index c546dade..e15fe018 100644 --- a/crates/tests/cgp-tests/tests/extensible_data_tests/variants/basic.rs +++ b/crates/tests/cgp-tests/tests/extensible_data_tests/variants/basic.rs @@ -12,6 +12,7 @@ use cgp::extra::handler::{ Computer, ComputerComponent, ComputerRef, ComputerRefComponent, PromoteAsync, }; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_new_provider, snapshot_delegate_components}; use futures::executor::block_on; #[derive(Debug, Eq, PartialEq, CgpData)] @@ -127,9 +128,28 @@ fn test_downcast() { pub struct App; -delegate_components! { - App { - ErrorTypeProviderComponent: UseType, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: UseType, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType< + Infallible, + >: IsProviderFor, + {} + ") } } @@ -212,15 +232,41 @@ fn test_dispatch_values_ref() { ); } -#[cgp_new_provider] -impl Computer for ValueToString -where - Value: Display, -{ - type Output = String; +snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Computer for ValueToString + where + Value: Display, + { + type Output = String; + + fn compute(_context: &Context, _code: PhantomData, input: &Value) -> Self::Output { + input.to_string() + } + } - fn compute(_context: &Context, _code: PhantomData, input: &Value) -> Self::Output { - input.to_string() + expand_value_to_string(output) { + insta::assert_snapshot!(output, @" + impl Computer for ValueToString + where + Value: Display, + { + type Output = String; + fn compute( + _context: &Context, + _code: PhantomData, + input: &Value, + ) -> Self::Output { + input.to_string() + } + } + impl IsProviderFor + for ValueToString + where + Value: Display, + {} + pub struct ValueToString; + ") } } diff --git a/crates/tests/cgp-tests/tests/extensible_data_tests/variants/shape.rs b/crates/tests/cgp-tests/tests/extensible_data_tests/variants/shape.rs index 83c07bb5..d2024e6c 100644 --- a/crates/tests/cgp-tests/tests/extensible_data_tests/variants/shape.rs +++ b/crates/tests/cgp-tests/tests/extensible_data_tests/variants/shape.rs @@ -8,6 +8,7 @@ use cgp::extra::dispatch::{ }; use cgp::extra::handler::{NoCode, UseInputDelegate}; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_components}; #[derive(Debug, PartialEq, CgpData)] pub enum Shape { @@ -187,28 +188,99 @@ fn test_dispatch_contains() { pub struct App; -delegate_components! { - App { - ComputerComponent: UseInputDelegate +snapshot_delegate_components! { + delegate_components! { + App { + ComputerComponent: UseInputDelegate + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + pub struct AreaComputers; + impl DelegateComponent for App { + type Delegate = UseInputDelegate; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseInputDelegate< + AreaComputers, + >: IsProviderFor, + {} + impl DelegateComponent for AreaComputers { + type Delegate = ComputeArea; + } + impl<__Context__, __Params__> IsProviderFor + for AreaComputers + where + ComputeArea: IsProviderFor, + {} + impl DelegateComponent for AreaComputers { + type Delegate = ComputeArea; + } + impl<__Context__, __Params__> IsProviderFor + for AreaComputers + where + ComputeArea: IsProviderFor, + {} + impl DelegateComponent for AreaComputers { + type Delegate = ComputeArea; + } + impl<__Context__, __Params__> IsProviderFor + for AreaComputers + where + ComputeArea: IsProviderFor, + {} + impl DelegateComponent for AreaComputers { + type Delegate = MatchWithValueHandlers; + } + impl<__Context__, __Params__> IsProviderFor + for AreaComputers + where + MatchWithValueHandlers: IsProviderFor, + {} + impl DelegateComponent for AreaComputers { + type Delegate = MatchWithValueHandlers; + } + impl<__Context__, __Params__> IsProviderFor + for AreaComputers + where + MatchWithValueHandlers: IsProviderFor, + {} + ") } } -check_components! { - App { - ComputerComponent: [ - ((), Shape), - ((), ShapePlus), - ], +snapshot_check_components! { + check_components! { + App { + ComputerComponent: [ + ((), Shape), + ((), ShapePlus), + ], + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/explicit.rs b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/explicit.rs index 813b02cb..5d5d5dc4 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/explicit.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/explicit.rs @@ -1,62 +1,340 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_auto_getter, snapshot_cgp_getter, snapshot_cgp_type}; -#[test] -pub fn test_abstract_type_getter() { +snapshot_cgp_type! { #[cgp_type] - pub trait HasNameType { - type Name; + pub trait HasScalarType { + type Scalar: Copy; } - #[cgp_getter] - pub trait HasName: HasNameType { - fn name(&self) -> &Self::Name; + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Copy; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar: Copy; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar: Copy, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar: Copy, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + {} + ") } +} + +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + #[extend(HasScalarType)] + pub trait AutoRectangleFields { + fn width(&self) -> Self::Scalar; - #[derive(HasField)] - pub struct App { - pub name: String, + fn height(&self) -> Self::Scalar; } - delegate_components! { - App { - NameTypeProviderComponent: UseType, - NameGetterComponent: UseField, + expand_auto_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait AutoRectangleFields: HasScalarType { + fn width(&self) -> Self::Scalar; + fn height(&self) -> Self::Scalar; } + impl<__Context__> AutoRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = __Context__::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = __Context__::Scalar, + >, + { + fn width(&self) -> __Context__::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(&self) -> __Context__::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + ") } - - let context = App { - name: "Alice".to_owned(), - }; - - assert_eq!(context.name(), "Alice"); } -#[test] -pub fn test_abstract_type_auto_getter() { - #[cgp_type] - pub trait HasNameType { - type Name; - } +snapshot_cgp_getter! { + #[cgp_getter(RectangleFieldsGetter)] + #[extend(HasScalarType)] + pub trait HasRectangleFields { + fn width(&self) -> Self::Scalar; - #[cgp_auto_getter] - pub trait HasName: HasNameType { - fn name(&self) -> &Self::Name; + fn height(&self) -> Self::Scalar; } - #[derive(HasField)] - pub struct App { - pub name: String, - } - - delegate_components! { - App { - NameTypeProviderComponent: UseType, + expand_has_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait HasRectangleFields: HasScalarType { + fn width(&self) -> Self::Scalar; + fn height(&self) -> Self::Scalar; + } + impl<__Context__> HasRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: RectangleFieldsGetter<__Context__>, + { + fn width(&self) -> Self::Scalar { + __Context__::width(self) + } + fn height(&self) -> Self::Scalar { + __Context__::height(self) + } + } + pub trait RectangleFieldsGetter< + __Context__, + >: IsProviderFor + where + __Context__: HasScalarType, + { + fn width(__context__: &__Context__) -> __Context__::Scalar; + fn height(__context__: &__Context__) -> __Context__::Scalar; } + impl<__Provider__, __Context__> RectangleFieldsGetter<__Context__> for __Provider__ + where + __Context__: HasScalarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> __Context__::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> __Context__::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::height(__context__) + } + } + pub struct RectangleFieldsGetterComponent; + impl<__Context__> RectangleFieldsGetter<__Context__> for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + { + fn width(__context__: &__Context__) -> __Context__::Scalar { + __Context__::width(__context__) + } + fn height(__context__: &__Context__) -> __Context__::Scalar { + __Context__::height(__context__) + } + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + {} + impl<__Context__, __Components__, __Path__> RectangleFieldsGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> __Context__::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> __Context__::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::height(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + RectangleFieldsGetter<__Context__>, + {} + impl<__Context__> RectangleFieldsGetter<__Context__> for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = __Context__::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = __Context__::Scalar, + >, + { + fn width(__context__: &__Context__) -> __Context__::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(__context__: &__Context__) -> __Context__::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + impl<__Context__> IsProviderFor + for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = __Context__::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = __Context__::Scalar, + >, + {} + ") } - - let context = App { - name: "Alice".to_owned(), - }; - - assert_eq!(context.name(), "Alice"); } diff --git a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/import.rs b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/import.rs index 87e1c178..ecbf733a 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/import.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/import.rs @@ -1,22 +1,340 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_auto_getter, snapshot_cgp_getter, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar: Copy; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar: Copy; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Copy; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar: Copy; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar: Copy, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar: Copy, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + {} + ") + } } -#[cgp_auto_getter] -#[extend(HasScalarType)] -pub trait AutoRectangleFields { - fn width(&self) -> Self::Scalar; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + #[use_type(HasScalarType::Scalar)] + pub trait AutoRectangleFields { + fn width(&self) -> Scalar; + + fn height(&self) -> Scalar; + } - fn height(&self) -> Self::Scalar; + expand_auto_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait AutoRectangleFields: HasScalarType { + fn width(&self) -> ::Scalar; + fn height(&self) -> ::Scalar; + } + impl<__Context__> AutoRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + { + fn width(&self) -> <__Context__ as HasScalarType>::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(&self) -> <__Context__ as HasScalarType>::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + ") + } } -#[cgp_getter(RectangleFieldsGetter)] -#[extend(HasScalarType)] -pub trait HasRectangleFields { - fn width(&self) -> Self::Scalar; +snapshot_cgp_getter! { + #[cgp_getter(RectangleFieldsGetter)] + #[use_type(HasScalarType::Scalar)] + pub trait HasRectangleFields { + fn width(&self) -> Scalar; + + fn height(&self) -> Scalar; + } - fn height(&self) -> Self::Scalar; + expand_has_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait HasRectangleFields: HasScalarType { + fn width(&self) -> ::Scalar; + fn height(&self) -> ::Scalar; + } + impl<__Context__> HasRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: RectangleFieldsGetter<__Context__>, + { + fn width(&self) -> ::Scalar { + __Context__::width(self) + } + fn height(&self) -> ::Scalar { + __Context__::height(self) + } + } + pub trait RectangleFieldsGetter< + __Context__, + >: IsProviderFor + where + __Context__: HasScalarType, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar; + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar; + } + impl<__Provider__, __Context__> RectangleFieldsGetter<__Context__> for __Provider__ + where + __Context__: HasScalarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::height(__context__) + } + } + pub struct RectangleFieldsGetterComponent; + impl<__Context__> RectangleFieldsGetter<__Context__> for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __Context__::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __Context__::height(__context__) + } + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + {} + impl<__Context__, __Components__, __Path__> RectangleFieldsGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::height(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + RectangleFieldsGetter<__Context__>, + {} + impl<__Context__> RectangleFieldsGetter<__Context__> for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + impl<__Context__> IsProviderFor + for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + {} + ") + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/use_type.rs b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/use_type.rs index bee751e3..ecbf733a 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/abstract_type/use_type.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/abstract_type/use_type.rs @@ -1,22 +1,340 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_auto_getter, snapshot_cgp_getter, snapshot_cgp_type}; -#[cgp_type] -pub trait HasScalarType { - type Scalar: Copy; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasScalarType { + type Scalar: Copy; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Copy; + } + impl<__Context__> HasScalarType for __Context__ + where + __Context__: ScalarTypeProvider<__Context__>, + { + type Scalar = <__Context__ as ScalarTypeProvider<__Context__>>::Scalar; + } + pub trait ScalarTypeProvider< + __Context__, + >: IsProviderFor { + type Scalar: Copy; + } + impl<__Provider__, __Context__> ScalarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarTypeProviderComponent, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + pub struct ScalarTypeProviderComponent; + impl<__Context__> ScalarTypeProvider<__Context__> for UseContext + where + __Context__: HasScalarType, + { + type Scalar = <__Context__ as HasScalarType>::Scalar; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + {} + impl<__Context__, __Components__, __Path__> ScalarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: ScalarTypeProvider<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarTypeProvider<__Context__>>::Scalar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarTypeProvider<__Context__>, + {} + impl ScalarTypeProvider<__Context__> for UseType + where + Scalar: Copy, + { + type Scalar = Scalar; + } + impl IsProviderFor + for UseType + where + Scalar: Copy, + {} + impl<__Provider__, Scalar, __Context__> ScalarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + { + type Scalar = Scalar; + } + impl< + __Provider__, + Scalar, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, ScalarTypeProviderComponent, Type = Scalar>, + Scalar: Copy, + {} + ") + } } -#[cgp_auto_getter] -#[use_type(HasScalarType::Scalar)] -pub trait AutoRectangleFields { - fn width(&self) -> Scalar; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + #[use_type(HasScalarType::Scalar)] + pub trait AutoRectangleFields { + fn width(&self) -> Scalar; + + fn height(&self) -> Scalar; + } - fn height(&self) -> Scalar; + expand_auto_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait AutoRectangleFields: HasScalarType { + fn width(&self) -> ::Scalar; + fn height(&self) -> ::Scalar; + } + impl<__Context__> AutoRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + { + fn width(&self) -> <__Context__ as HasScalarType>::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(&self) -> <__Context__ as HasScalarType>::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + ") + } } -#[cgp_getter(RectangleFieldsGetter)] -#[use_type(HasScalarType::Scalar)] -pub trait HasRectangleFields { - fn width(&self) -> Scalar; +snapshot_cgp_getter! { + #[cgp_getter(RectangleFieldsGetter)] + #[use_type(HasScalarType::Scalar)] + pub trait HasRectangleFields { + fn width(&self) -> Scalar; + + fn height(&self) -> Scalar; + } - fn height(&self) -> Scalar; + expand_has_rectangle_fields(output) { + insta::assert_snapshot!(output, @" + pub trait HasRectangleFields: HasScalarType { + fn width(&self) -> ::Scalar; + fn height(&self) -> ::Scalar; + } + impl<__Context__> HasRectangleFields for __Context__ + where + __Context__: HasScalarType, + __Context__: RectangleFieldsGetter<__Context__>, + { + fn width(&self) -> ::Scalar { + __Context__::width(self) + } + fn height(&self) -> ::Scalar { + __Context__::height(self) + } + } + pub trait RectangleFieldsGetter< + __Context__, + >: IsProviderFor + where + __Context__: HasScalarType, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar; + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar; + } + impl<__Provider__, __Context__> RectangleFieldsGetter<__Context__> for __Provider__ + where + __Context__: HasScalarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Provider__ as DelegateComponent< + RectangleFieldsGetterComponent, + >>::Delegate::height(__context__) + } + } + pub struct RectangleFieldsGetterComponent; + impl<__Context__> RectangleFieldsGetter<__Context__> for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __Context__::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __Context__::height(__context__) + } + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasScalarType, + __Context__: HasRectangleFields, + {} + impl<__Context__, __Components__, __Path__> RectangleFieldsGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: RectangleFieldsGetter<__Context__>, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::width(__context__) + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::height(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasScalarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + RectangleFieldsGetter<__Context__>, + {} + impl<__Context__> RectangleFieldsGetter<__Context__> for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + { + fn width(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 5, + Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>, + >, + >, + ) + .clone() + } + fn height(__context__: &__Context__) -> <__Context__ as HasScalarType>::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 'h', + Chars< + 'e', + Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>, + >, + >, + >, + >, + ) + .clone() + } + } + impl<__Context__> IsProviderFor + for UseFields + where + __Context__: HasScalarType, + __Context__: HasField< + Symbol<5, Chars<'w', Chars<'i', Chars<'d', Chars<'t', Chars<'h', Nil>>>>>>, + Value = <__Context__ as HasScalarType>::Scalar, + >, + __Context__: HasField< + Symbol< + 6, + Chars<'h', Chars<'e', Chars<'i', Chars<'g', Chars<'h', Chars<'t', Nil>>>>>>, + >, + Value = <__Context__ as HasScalarType>::Scalar, + >, + {} + ") + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/auto_getter.rs b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/auto_getter.rs index ad6c03a5..28c20431 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/auto_getter.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/auto_getter.rs @@ -1,12 +1,41 @@ use core::fmt::Display; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_auto_getter; -#[cgp_auto_getter] -pub trait HasName { - type Name: Display; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasName { + type Name: Display; - fn name(&self) -> &Self::Name; + fn name(&self) -> &Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName { + type Name: Display; + fn name(&self) -> &Self::Name; + } + impl<__Context__, Name> HasName for __Context__ + where + Name: Display, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = Name, + >, + { + type Name = Name; + fn name(&self) -> &Self::Name { + self.get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/getter.rs b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/getter.rs index 441a4941..6b5abdae 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/getter.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/getter.rs @@ -1,25 +1,213 @@ -use core::fmt::Display; +use core::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; -#[cgp_getter] -pub trait HasName { - type Name: Display; +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasScalar { + type Scalar: Mul + Clone; - fn name(&self) -> &Self::Name; + fn scalar(&self) -> &Self::Scalar; + } + + expand_has_scalar(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalar { + type Scalar: Mul + Clone; + fn scalar(&self) -> &Self::Scalar; + } + impl<__Context__> HasScalar for __Context__ + where + __Context__: ScalarGetter<__Context__>, + { + type Scalar = <__Context__ as ScalarGetter<__Context__>>::Scalar; + fn scalar(&self) -> &Self::Scalar { + __Context__::scalar(self) + } + } + pub trait ScalarGetter< + __Context__, + >: IsProviderFor { + type Scalar: Mul + Clone; + fn scalar(__context__: &__Context__) -> &Self::Scalar; + } + impl<__Provider__, __Context__> ScalarGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + ScalarGetterComponent, + >>::Delegate: ScalarGetter<__Context__>, + { + type Scalar = <<__Provider__ as DelegateComponent< + ScalarGetterComponent, + >>::Delegate as ScalarGetter<__Context__>>::Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + <__Provider__ as DelegateComponent< + ScalarGetterComponent, + >>::Delegate::scalar(__context__) + } + } + pub struct ScalarGetterComponent; + impl<__Context__> ScalarGetter<__Context__> for UseContext + where + __Context__: HasScalar, + { + type Scalar = <__Context__ as HasScalar>::Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + __Context__::scalar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasScalar, + {} + impl<__Context__, __Components__, __Path__> ScalarGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: ScalarGetter<__Context__>, + { + type Scalar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as ScalarGetter<__Context__>>::Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::scalar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + ScalarGetter<__Context__>, + {} + impl<__Context__, Scalar> ScalarGetter<__Context__> for UseFields + where + Scalar: Mul + Clone, + __Context__: HasField< + Symbol< + 6, + Chars<'s', Chars<'c', Chars<'a', Chars<'l', Chars<'a', Chars<'r', Nil>>>>>>, + >, + Value = Scalar, + >, + { + type Scalar = Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 's', + Chars< + 'c', + Chars<'a', Chars<'l', Chars<'a', Chars<'r', Nil>>>>, + >, + >, + >, + >, + ) + } + } + impl<__Context__, Scalar> IsProviderFor + for UseFields + where + Scalar: Mul + Clone, + __Context__: HasField< + Symbol< + 6, + Chars<'s', Chars<'c', Chars<'a', Chars<'l', Chars<'a', Chars<'r', Nil>>>>>>, + >, + Value = Scalar, + >, + {} + impl<__Context__, Scalar, __Tag__> ScalarGetter<__Context__> for UseField<__Tag__> + where + Scalar: Mul + Clone, + __Context__: HasField<__Tag__, Value = Scalar>, + { + type Scalar = Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, Scalar, __Tag__> IsProviderFor + for UseField<__Tag__> + where + Scalar: Mul + Clone, + __Context__: HasField<__Tag__, Value = Scalar>, + {} + impl<__Context__, Scalar, __Provider__> ScalarGetter<__Context__> + for WithProvider<__Provider__> + where + Scalar: Mul + Clone, + __Provider__: FieldGetter<__Context__, ScalarGetterComponent, Value = Scalar>, + { + type Scalar = Scalar; + fn scalar(__context__: &__Context__) -> &Self::Scalar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl< + __Context__, + Scalar, + __Provider__, + > IsProviderFor for WithProvider<__Provider__> + where + Scalar: Mul + Clone, + __Provider__: FieldGetter<__Context__, ScalarGetterComponent, Value = Scalar>, + {} + ") + } } #[derive(HasField)] -pub struct Person { - pub first_name: String, +pub struct App { + pub scalar: f64, } -delegate_components! { - Person { - NameGetterComponent: - UseField, +snapshot_delegate_components! { + delegate_components! { + App { + ScalarGetterComponent: + UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseField< + Symbol!("scalar"), + >: IsProviderFor, + {} + "#) } } -pub trait CheckHasName: HasName {} -impl CheckHasName for Person {} +#[test] +fn test_auto_getter_scalar() { + let app = App { scalar: 2.0 }; + + assert_eq!(*app.scalar(), 2.0); +} diff --git a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential.rs b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential.rs index e3aa8502..40abfa1e 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential.rs @@ -1,29 +1,186 @@ -use core::ops::Mul; +use core::fmt::Display; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; -#[cgp_getter] -pub trait HasScalar { - type Scalar: Mul + Clone; +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName { + type Name: Display; - fn scalar(&self) -> &Self::Scalar; + fn name(&self) -> &Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName { + type Name: Display; + fn name(&self) -> &Self::Name; + } + impl<__Context__> HasName for __Context__ + where + __Context__: NameGetter<__Context__>, + { + type Name = <__Context__ as NameGetter<__Context__>>::Name; + fn name(&self) -> &Self::Name { + __Context__::name(self) + } + } + pub trait NameGetter<__Context__>: IsProviderFor { + type Name: Display; + fn name(__context__: &__Context__) -> &Self::Name; + } + impl<__Provider__, __Context__> NameGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate: NameGetter<__Context__>, + { + type Name = <<__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate as NameGetter<__Context__>>::Name; + fn name(__context__: &__Context__) -> &Self::Name { + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate::name(__context__) + } + } + pub struct NameGetterComponent; + impl<__Context__> NameGetter<__Context__> for UseContext + where + __Context__: HasName, + { + type Name = <__Context__ as HasName>::Name; + fn name(__context__: &__Context__) -> &Self::Name { + __Context__::name(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasName, + {} + impl<__Context__, __Components__, __Path__> NameGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: NameGetter<__Context__>, + { + type Name = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as NameGetter<__Context__>>::Name; + fn name(__context__: &__Context__) -> &Self::Name { + <__Components__ as DelegateComponent<__Path__>>::Delegate::name(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameGetter<__Context__>, + {} + impl<__Context__, Name> NameGetter<__Context__> for UseFields + where + Name: Display, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = Name, + >, + { + type Name = Name; + fn name(__context__: &__Context__) -> &Self::Name { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + } + } + impl<__Context__, Name> IsProviderFor for UseFields + where + Name: Display, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = Name, + >, + {} + impl<__Context__, Name, __Tag__> NameGetter<__Context__> for UseField<__Tag__> + where + Name: Display, + __Context__: HasField<__Tag__, Value = Name>, + { + type Name = Name; + fn name(__context__: &__Context__) -> &Self::Name { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, Name, __Tag__> IsProviderFor + for UseField<__Tag__> + where + Name: Display, + __Context__: HasField<__Tag__, Value = Name>, + {} + impl<__Context__, Name, __Provider__> NameGetter<__Context__> + for WithProvider<__Provider__> + where + Name: Display, + __Provider__: FieldGetter<__Context__, NameGetterComponent, Value = Name>, + { + type Name = Name; + fn name(__context__: &__Context__) -> &Self::Name { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, Name, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + Name: Display, + __Provider__: FieldGetter<__Context__, NameGetterComponent, Value = Name>, + {} + ") + } } #[derive(HasField)] -pub struct App { - pub scalar: f64, +pub struct Person { + pub first_name: String, } -delegate_components! { - App { - ScalarGetterComponent: - UseField, +snapshot_delegate_components! { + delegate_components! { + Person { + NameGetterComponent: + UseField, + } } -} -#[test] -fn test_auto_getter_scalar() { - let app = App { scalar: 2.0 }; - - assert_eq!(*app.scalar(), 2.0); + expand_person(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for Person { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for Person + where + UseField< + Symbol!("first_name"), + >: IsProviderFor, + {} + "#) + } } + +pub trait CheckHasName: HasName {} +impl CheckHasName for Person {} diff --git a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential_auto.rs b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential_auto.rs index b054d784..8ac420c6 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential_auto.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/assoc_type/self_referential_auto.rs @@ -1,12 +1,50 @@ use core::ops::Mul; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_auto_getter; -#[cgp_auto_getter] -pub trait HasScalarType { - type Scalar: Mul + Clone; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasScalarType { + type Scalar: Mul + Clone; - fn scalar(&self) -> &Self::Scalar; + fn scalar(&self) -> &Self::Scalar; + } + + expand_has_scalar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasScalarType { + type Scalar: Mul + Clone; + fn scalar(&self) -> &Self::Scalar; + } + impl<__Context__, Scalar> HasScalarType for __Context__ + where + Scalar: Mul + Clone, + __Context__: HasField< + Symbol< + 6, + Chars<'s', Chars<'c', Chars<'a', Chars<'l', Chars<'a', Chars<'r', Nil>>>>>>, + >, + Value = Scalar, + >, + { + type Scalar = Scalar; + fn scalar(&self) -> &Self::Scalar { + self.get_field( + ::core::marker::PhantomData::< + Symbol< + 6, + Chars< + 's', + Chars<'c', Chars<'a', Chars<'l', Chars<'a', Chars<'r', Nil>>>>>, + >, + >, + >, + ) + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/getter_tests/auto_generics.rs b/crates/tests/cgp-tests/tests/getter_tests/auto_generics.rs index e38595f3..0e68c9c3 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/auto_generics.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/auto_generics.rs @@ -1,8 +1,34 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_cgp_auto_getter; -#[cgp_auto_getter] -pub trait HasFoo { - fn foo(&self, _tag: PhantomData) -> &Foo; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFoo { + fn foo(&self, _tag: PhantomData) -> &Foo; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self, _tag: PhantomData) -> &Foo; + } + impl<__Context__, Foo> HasFoo for __Context__ + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = Foo, + >, + { + fn foo(&self, _phantom: PhantomData) -> &Foo { + self.get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + ") + } } #[derive(HasField)] diff --git a/crates/tests/cgp-tests/tests/getter_tests/clone.rs b/crates/tests/cgp-tests/tests/getter_tests/clone.rs index d01b2118..4355a627 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/clone.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/clone.rs @@ -1,15 +1,264 @@ -use cgp::prelude::*; +mod clone_getter { + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_getter, snapshot_cgp_type, snapshot_delegate_components, + }; -#[test] -pub fn test_clone_getter() { - #[cgp_type] - pub trait HasNameType { - type Name; + snapshot_cgp_type! { + #[cgp_type] + pub trait HasNameType { + type Name; + } + + expand_has_name_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasNameType { + type Name; + } + impl<__Context__> HasNameType for __Context__ + where + __Context__: NameTypeProvider<__Context__>, + { + type Name = <__Context__ as NameTypeProvider<__Context__>>::Name; + } + pub trait NameTypeProvider< + __Context__, + >: IsProviderFor { + type Name; + } + impl<__Provider__, __Context__> NameTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + pub struct NameTypeProviderComponent; + impl<__Context__> NameTypeProvider<__Context__> for UseContext + where + __Context__: HasNameType, + { + type Name = <__Context__ as HasNameType>::Name; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasNameType, + {} + impl<__Context__, __Components__, __Path__> NameTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameTypeProvider<__Context__>, + {} + impl NameTypeProvider<__Context__> for UseType + where + Name:, + { + type Name = Name; + } + impl IsProviderFor + for UseType + where + Name:, + {} + impl<__Provider__, Name, __Context__> NameTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + { + type Name = Name; + } + impl< + __Provider__, + Name, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + {} + ") + } } - #[cgp_getter] - pub trait HasName: HasNameType { - fn name(&self) -> Self::Name; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasName: HasNameType { + fn name(&self) -> Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName: HasNameType { + fn name(&self) -> Self::Name; + } + impl<__Context__> HasName for __Context__ + where + __Context__: HasNameType, + __Context__: NameGetter<__Context__>, + { + fn name(&self) -> Self::Name { + __Context__::name(self) + } + } + pub trait NameGetter<__Context__>: IsProviderFor + where + __Context__: HasNameType, + { + fn name(__context__: &__Context__) -> __Context__::Name; + } + impl<__Provider__, __Context__> NameGetter<__Context__> for __Provider__ + where + __Context__: HasNameType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> __Context__::Name { + <__Provider__ as DelegateComponent< + NameGetterComponent, + >>::Delegate::name(__context__) + } + } + pub struct NameGetterComponent; + impl<__Context__> NameGetter<__Context__> for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + { + fn name(__context__: &__Context__) -> __Context__::Name { + __Context__::name(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasNameType, + __Context__: HasName, + {} + impl<__Context__, __Components__, __Path__> NameGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: NameGetter<__Context__>, + { + fn name(__context__: &__Context__) -> __Context__::Name { + <__Components__ as DelegateComponent<__Path__>>::Delegate::name(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasNameType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameGetter<__Context__>, + {} + impl<__Context__> NameGetter<__Context__> for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> __Context__::Name { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .clone() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + {} + impl<__Context__, __Tag__> NameGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + { + fn name(__context__: &__Context__) -> __Context__::Name { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).clone() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasNameType, + __Context__: HasField<__Tag__, Value = __Context__::Name>, + {} + impl<__Context__, __Provider__> NameGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + { + fn name(__context__: &__Context__) -> __Context__::Name { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .clone() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasNameType, + __Provider__: FieldGetter< + __Context__, + NameGetterComponent, + Value = __Context__::Name, + >, + {} + ") + } } #[derive(HasField)] @@ -17,28 +266,190 @@ pub fn test_clone_getter() { pub name: &'static str, } - delegate_components! { - App { - NameTypeProviderComponent: UseType<&'static str>, - NameGetterComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + NameTypeProviderComponent: UseType<&'static str>, + NameGetterComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseType<&'static str>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType< + &'static str, + >: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField< + Symbol!("name"), + >: IsProviderFor, + {} + "#) } } - let context = App { name: "Alice" }; + #[test] + pub fn test_clone_getter() { + let context = App { name: "Alice" }; - assert_eq!(context.name(), "Alice"); + assert_eq!(context.name(), "Alice"); + } } -#[test] -pub fn test_clone_auto_getter() { - #[cgp_type] - pub trait HasNameType { - type Name; +mod clone_auto_getter { + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_auto_getter, snapshot_cgp_type, snapshot_delegate_components, + }; + + snapshot_cgp_type! { + #[cgp_type] + pub trait HasNameType { + type Name; + } + + expand_has_name_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasNameType { + type Name; + } + impl<__Context__> HasNameType for __Context__ + where + __Context__: NameTypeProvider<__Context__>, + { + type Name = <__Context__ as NameTypeProvider<__Context__>>::Name; + } + pub trait NameTypeProvider< + __Context__, + >: IsProviderFor { + type Name; + } + impl<__Provider__, __Context__> NameTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Provider__ as DelegateComponent< + NameTypeProviderComponent, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + pub struct NameTypeProviderComponent; + impl<__Context__> NameTypeProvider<__Context__> for UseContext + where + __Context__: HasNameType, + { + type Name = <__Context__ as HasNameType>::Name; + } + impl<__Context__> IsProviderFor + for UseContext + where + __Context__: HasNameType, + {} + impl<__Context__, __Components__, __Path__> NameTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: NameTypeProvider<__Context__>, + { + type Name = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as NameTypeProvider<__Context__>>::Name; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + NameTypeProvider<__Context__>, + {} + impl NameTypeProvider<__Context__> for UseType + where + Name:, + { + type Name = Name; + } + impl IsProviderFor + for UseType + where + Name:, + {} + impl<__Provider__, Name, __Context__> NameTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + { + type Name = Name; + } + impl< + __Provider__, + Name, + __Context__, + > IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, NameTypeProviderComponent, Type = Name>, + Name:, + {} + ") + } } - #[cgp_auto_getter] - pub trait HasName: HasNameType { - fn name(&self) -> Self::Name; + snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasName: HasNameType { + fn name(&self) -> Self::Name; + } + + expand_has_name(output) { + insta::assert_snapshot!(output, @" + pub trait HasName: HasNameType { + fn name(&self) -> Self::Name; + } + impl<__Context__> HasName for __Context__ + where + __Context__: HasNameType, + __Context__: HasField< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + Value = __Context__::Name, + >, + { + fn name(&self) -> __Context__::Name { + self.get_field( + ::core::marker::PhantomData::< + Symbol<4, Chars<'n', Chars<'a', Chars<'m', Chars<'e', Nil>>>>>, + >, + ) + .clone() + } + } + ") + } } #[derive(HasField)] @@ -46,13 +457,35 @@ pub fn test_clone_auto_getter() { pub name: &'static str, } - delegate_components! { - App { - NameTypeProviderComponent: UseType<&'static str>, + snapshot_delegate_components! { + delegate_components! { + App { + NameTypeProviderComponent: UseType<&'static str>, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType<&'static str>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType< + &'static str, + >: IsProviderFor, + {} + ") } } - let context = App { name: "Alice" }; + #[test] + pub fn test_clone_auto_getter() { + let context = App { name: "Alice" }; - assert_eq!(context.name(), "Alice"); + assert_eq!(context.name(), "Alice"); + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/mref.rs b/crates/tests/cgp-tests/tests/getter_tests/mref.rs index 24645185..f703e842 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/mref.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/mref.rs @@ -1,11 +1,138 @@ -use cgp::core::field::types::MRef; -use cgp::prelude::*; - -#[test] -pub fn test_mref_getter() { - #[cgp_getter] - pub trait HasFoo { - fn foo(&self) -> MRef<'_, String>; +mod mref_getter { + use cgp::core::field::types::MRef; + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; + + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFoo { + fn foo(&self) -> MRef<'_, String>; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> MRef<'_, String>; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: FooGetter<__Context__>, + { + fn foo(&self) -> MRef<'_, String> { + __Context__::foo(self) + } + } + pub trait FooGetter<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> MRef<'_, String>; + } + impl<__Provider__, __Context__> FooGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooGetterComponent; + impl<__Context__> FooGetter<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> FooGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooGetter<__Context__>, + {} + impl<__Context__> FooGetter<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + MRef::Ref( + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ), + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + {} + impl<__Context__, __Tag__> FooGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + MRef::Ref(__context__.get_field(::core::marker::PhantomData::<__Tag__>)) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + {} + impl<__Context__, __Provider__> FooGetter<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = String>, + { + fn foo(__context__: &__Context__) -> MRef<'_, String> { + MRef::Ref( + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ), + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = String>, + {} + ") + } } #[derive(HasField)] @@ -13,22 +140,71 @@ pub fn test_mref_getter() { pub bar: String, } - delegate_components! { - App { - FooGetterComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + FooGetterComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { bar: "foo".into() }; + #[test] + pub fn test_mref_getter() { + let context = App { bar: "foo".into() }; - assert_eq!(context.foo().as_ref(), "foo"); + assert_eq!(context.foo().as_ref(), "foo"); + } } -#[test] -pub fn test_mref_auto_getter() { - #[cgp_auto_getter] - pub trait HasFoo { - fn foo(&self) -> MRef<'_, String>; +mod mref_auto_getter { + use cgp::core::field::types::MRef; + use cgp::prelude::*; + use cgp_macro_test_util::snapshot_cgp_auto_getter; + + snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFoo { + fn foo(&self) -> MRef<'_, String>; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> MRef<'_, String>; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(&self) -> MRef<'_, String> { + MRef::Ref( + self + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ), + ) + } + } + ") + } } #[derive(HasField)] @@ -36,7 +212,10 @@ pub fn test_mref_auto_getter() { pub foo: String, } - let context = App { foo: "foo".into() }; + #[test] + pub fn test_mref_auto_getter() { + let context = App { foo: "foo".into() }; - assert_eq!(context.foo().as_ref(), "foo"); + assert_eq!(context.foo().as_ref(), "foo"); + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/non_self.rs b/crates/tests/cgp-tests/tests/getter_tests/non_self.rs index fdb576b4..0af7397b 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/non_self.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/non_self.rs @@ -1,18 +1,391 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_cgp_type, snapshot_delegate_components}; -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_getter] -pub trait HasFooBar: HasFooType + HasBarType { - fn foo_bar(foo: &Self::Foo) -> &Self::Bar; +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFooBar: HasFooType + HasBarType { + fn foo_bar(foo: &Self::Foo) -> &Self::Bar; + } + + expand_has_foo_bar(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooBar: HasFooType + HasBarType { + fn foo_bar(foo: &Self::Foo) -> &Self::Bar; + } + impl<__Context__> HasFooBar for __Context__ + where + __Context__: HasFooType + HasBarType, + __Context__: FooBarGetter<__Context__>, + { + fn foo_bar(foo: &Self::Foo) -> &Self::Bar { + __Context__::foo_bar(foo) + } + } + pub trait FooBarGetter< + __Context__, + >: IsProviderFor + where + __Context__: HasFooType + HasBarType, + { + fn foo_bar(foo: &__Context__::Foo) -> &__Context__::Bar; + } + impl<__Provider__, __Context__> FooBarGetter<__Context__> for __Provider__ + where + __Context__: HasFooType + HasBarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooBarGetterComponent, + >>::Delegate: FooBarGetter<__Context__>, + { + fn foo_bar(foo: &__Context__::Foo) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + FooBarGetterComponent, + >>::Delegate::foo_bar(foo) + } + } + pub struct FooBarGetterComponent; + impl<__Context__> FooBarGetter<__Context__> for UseContext + where + __Context__: HasFooType + HasBarType, + __Context__: HasFooBar, + { + fn foo_bar(foo: &__Context__::Foo) -> &__Context__::Bar { + __Context__::foo_bar(foo) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType + HasBarType, + __Context__: HasFooBar, + {} + impl<__Context__, __Components__, __Path__> FooBarGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooBarGetter<__Context__>, + { + fn foo_bar(foo: &__Context__::Foo) -> &__Context__::Bar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo_bar(foo) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType + HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooBarGetter<__Context__>, + {} + impl<__Context__> FooBarGetter<__Context__> for UseFields + where + __Context__: HasFooType + HasBarType, + __Context__::Foo: HasField< + Symbol< + 7, + Chars< + 'f', + Chars< + 'o', + Chars<'o', Chars<'_', Chars<'b', Chars<'a', Chars<'r', Nil>>>>>, + >, + >, + >, + Value = __Context__::Bar, + >, + { + fn foo_bar(__context__: &__Context__::Foo) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 7, + Chars< + 'f', + Chars< + 'o', + Chars< + 'o', + Chars<'_', Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasFooType + HasBarType, + __Context__::Foo: HasField< + Symbol< + 7, + Chars< + 'f', + Chars< + 'o', + Chars<'o', Chars<'_', Chars<'b', Chars<'a', Chars<'r', Nil>>>>>, + >, + >, + >, + Value = __Context__::Bar, + >, + {} + impl<__Context__, __Tag__> FooBarGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasFooType + HasBarType, + __Context__::Foo: HasField<__Tag__, Value = __Context__::Bar>, + { + fn foo_bar(__context__: &__Context__::Foo) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasFooType + HasBarType, + __Context__::Foo: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, __Provider__> FooBarGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasFooType + HasBarType, + __Provider__: FieldGetter< + __Context__::Foo, + FooBarGetterComponent, + Value = __Context__::Bar, + >, + { + fn foo_bar(__context__: &__Context__::Foo) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasFooType + HasBarType, + __Provider__: FieldGetter< + __Context__::Foo, + FooBarGetterComponent, + Value = __Context__::Bar, + >, + {} + ") + } } pub struct App; @@ -22,14 +395,53 @@ pub struct Foo { pub bar: u32, } -delegate_components! { - App { - FooTypeProviderComponent: - UseType, - BarTypeProviderComponent: - UseType, - FooBarGetterComponent: - UseField, +snapshot_delegate_components! { + delegate_components! { + App { + FooTypeProviderComponent: + UseType, + BarTypeProviderComponent: + UseType, + FooBarGetterComponent: + UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseField; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseField< + Symbol!("bar"), + >: IsProviderFor, + {} + "#) } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/non_self_auto.rs b/crates/tests/cgp-tests/tests/getter_tests/non_self_auto.rs index 69affce1..f1bdeda6 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/non_self_auto.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/non_self_auto.rs @@ -1,18 +1,263 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_auto_getter, snapshot_cgp_type, snapshot_delegate_components, +}; -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_auto_getter] -pub trait HasFooBar: HasFooType + HasBarType { - fn foo_bar(foo: &Self::Foo) -> &Self::Bar; +snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFooBar: HasFooType + HasBarType { + fn foo_bar(foo: &Self::Foo) -> &Self::Bar; + } + + expand_has_foo_bar(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooBar: HasFooType + HasBarType { + fn foo_bar(foo: &Self::Foo) -> &Self::Bar; + } + impl<__Context__> HasFooBar for __Context__ + where + __Context__: HasFooType + HasBarType, + __Context__::Foo: HasField< + Symbol< + 7, + Chars< + 'f', + Chars< + 'o', + Chars<'o', Chars<'_', Chars<'b', Chars<'a', Chars<'r', Nil>>>>>, + >, + >, + >, + Value = __Context__::Bar, + >, + { + fn foo_bar(__context__: &__Context__::Foo) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol< + 7, + Chars< + 'f', + Chars< + 'o', + Chars< + 'o', + Chars<'_', Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + >, + >, + >, + >, + ) + } + } + ") + } } pub struct App; @@ -22,12 +267,39 @@ pub struct Foo { pub foo_bar: u32, } -delegate_components! { - App { - FooTypeProviderComponent: - UseType, - BarTypeProviderComponent: - UseType, +snapshot_delegate_components! { + delegate_components! { + App { + FooTypeProviderComponent: + UseType, + BarTypeProviderComponent: + UseType, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/option.rs b/crates/tests/cgp-tests/tests/getter_tests/option.rs index 683521e2..b8f626b2 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/option.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/option.rs @@ -1,10 +1,135 @@ -use cgp::prelude::*; +mod option_getter { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; -#[test] -pub fn test_option_getter() { - #[cgp_getter] - pub trait HasFoo { - fn foo(&self) -> Option<&String>; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFoo { + fn foo(&self) -> Option<&String>; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> Option<&String>; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: FooGetter<__Context__>, + { + fn foo(&self) -> Option<&String> { + __Context__::foo(self) + } + } + pub trait FooGetter<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> Option<&String>; + } + impl<__Provider__, __Context__> FooGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> Option<&String> { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooGetterComponent; + impl<__Context__> FooGetter<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> Option<&String> { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> FooGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> Option<&String> { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooGetter<__Context__>, + {} + impl<__Context__> FooGetter<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = Option, + >, + { + fn foo(__context__: &__Context__) -> Option<&String> { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_ref() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = Option, + >, + {} + impl<__Context__, __Tag__> FooGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = Option>, + { + fn foo(__context__: &__Context__) -> Option<&String> { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_ref() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = Option>, + {} + impl<__Context__, __Provider__> FooGetter<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = Option>, + { + fn foo(__context__: &__Context__) -> Option<&String> { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_ref() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = Option>, + {} + ") + } } #[derive(HasField)] @@ -12,24 +137,70 @@ pub fn test_option_getter() { pub bar: Option, } - delegate_components! { - App { - FooGetterComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + FooGetterComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { - bar: Some("foo".to_owned()), - }; + #[test] + pub fn test_option_getter() { + let context = App { + bar: Some("foo".to_owned()), + }; - assert_eq!(context.foo(), Some(&"foo".to_owned())); + assert_eq!(context.foo(), Some(&"foo".to_owned())); + } } -#[test] -pub fn test_option_auto_getter() { - #[cgp_auto_getter] - pub trait HasFoo { - fn foo(&self) -> Option<&String>; +mod option_auto_getter { + use cgp::prelude::*; + use cgp_macro_test_util::snapshot_cgp_auto_getter; + + snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFoo { + fn foo(&self) -> Option<&String>; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> Option<&String>; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = Option, + >, + { + fn foo(&self) -> Option<&String> { + self.get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_ref() + } + } + ") + } } #[derive(HasField)] @@ -37,9 +208,12 @@ pub fn test_option_auto_getter() { pub foo: Option, } - let context = App { - foo: Some("foo".to_owned()), - }; + #[test] + pub fn test_option_auto_getter() { + let context = App { + foo: Some("foo".to_owned()), + }; - assert_eq!(context.foo(), Some(&"foo".to_owned())); + assert_eq!(context.foo(), Some(&"foo".to_owned())); + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/slice.rs b/crates/tests/cgp-tests/tests/getter_tests/slice.rs index 51e35455..b6c9f926 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/slice.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/slice.rs @@ -1,10 +1,143 @@ -use cgp::prelude::*; +mod slice_getter { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; -#[test] -pub fn test_slice_getter() { - #[cgp_getter] - pub trait HasFoo { - fn foo(&self) -> &[u8]; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFoo { + fn foo(&self) -> &[u8]; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &[u8]; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: FooGetter<__Context__>, + { + fn foo(&self) -> &[u8] { + __Context__::foo(self) + } + } + pub trait FooGetter<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> &[u8]; + } + impl<__Provider__, __Context__> FooGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &[u8] { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooGetterComponent; + impl<__Context__> FooGetter<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> &[u8] { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> FooGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &[u8] { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooGetter<__Context__>, + {} + impl<__Context__> FooGetter<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value: AsRef<[u8]> + 'static, + >, + { + fn foo(__context__: &__Context__) -> &[u8] { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_ref() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value: AsRef<[u8]> + 'static, + >, + {} + impl<__Context__, __Tag__> FooGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value: AsRef<[u8]> + 'static>, + { + fn foo(__context__: &__Context__) -> &[u8] { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_ref() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value: AsRef<[u8]> + 'static>, + {} + impl<__Context__, __Provider__> FooGetter<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value: AsRef<[u8]> + 'static, + >, + { + fn foo(__context__: &__Context__) -> &[u8] { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_ref() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value: AsRef<[u8]> + 'static, + >, + {} + ") + } } #[derive(HasField)] @@ -12,22 +145,68 @@ pub fn test_slice_getter() { pub bar: Vec, } - delegate_components! { - App { - FooGetterComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + FooGetterComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { bar: vec![1, 2, 3] }; + #[test] + pub fn test_slice_getter() { + let context = App { bar: vec![1, 2, 3] }; - assert_eq!(context.foo(), &[1, 2, 3]); + assert_eq!(context.foo(), &[1, 2, 3]); + } } -#[test] -pub fn test_slice_auto_getter() { - #[cgp_auto_getter] - pub trait HasFoo { - fn foo(&self) -> &[u8]; +mod slice_auto_getter { + use cgp::prelude::*; + use cgp_macro_test_util::snapshot_cgp_auto_getter; + + snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFoo { + fn foo(&self) -> &[u8]; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &[u8]; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value: AsRef<[u8]> + 'static, + >, + { + fn foo(&self) -> &[u8] { + self.get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_ref() + } + } + ") + } } #[derive(HasField)] @@ -35,7 +214,10 @@ pub fn test_slice_auto_getter() { pub foo: Vec, } - let context = App { foo: vec![1, 2, 3] }; + #[test] + pub fn test_slice_auto_getter() { + let context = App { foo: vec![1, 2, 3] }; - assert_eq!(context.foo(), &[1, 2, 3]); + assert_eq!(context.foo(), &[1, 2, 3]); + } } diff --git a/crates/tests/cgp-tests/tests/getter_tests/string.rs b/crates/tests/cgp-tests/tests/getter_tests/string.rs index 02add9d9..bd94f9bd 100644 --- a/crates/tests/cgp-tests/tests/getter_tests/string.rs +++ b/crates/tests/cgp-tests/tests/getter_tests/string.rs @@ -1,10 +1,135 @@ -use cgp::prelude::*; +mod string_getter { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; -#[test] -pub fn test_string_getter() { - #[cgp_getter] - pub trait HasFoo { - fn foo(&self) -> &str; + snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFoo { + fn foo(&self) -> &str; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &str; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: FooGetter<__Context__>, + { + fn foo(&self) -> &str { + __Context__::foo(self) + } + } + pub trait FooGetter<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> &str; + } + impl<__Provider__, __Context__> FooGetter<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooGetterComponent; + impl<__Context__> FooGetter<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> &str { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> FooGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooGetter<__Context__>, + {} + impl<__Context__> FooGetter<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(__context__: &__Context__) -> &str { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_str() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + {} + impl<__Context__, __Tag__> FooGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_str() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + {} + impl<__Context__, __Provider__> FooGetter<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_str() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = String>, + {} + ") + } } #[derive(HasField)] @@ -12,24 +137,169 @@ pub fn test_string_getter() { pub bar: String, } - delegate_components! { - App { - FooGetterComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + FooGetterComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { - bar: "abc".to_owned(), - }; + #[test] + pub fn test_string_getter() { + let context = App { + bar: "abc".to_owned(), + }; - assert_eq!(context.foo(), "abc"); + assert_eq!(context.foo(), "abc"); + } } -#[test] -pub fn test_string_getter_with_custom_name() { - #[cgp_getter(GetString)] - pub trait HasFoo { - fn foo(&self) -> &str; +mod string_getter_with_custom_name { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; + + snapshot_cgp_getter! { + #[cgp_getter(GetString)] + pub trait HasFoo { + fn foo(&self) -> &str; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &str; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: GetString<__Context__>, + { + fn foo(&self) -> &str { + __Context__::foo(self) + } + } + pub trait GetString<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> &str; + } + impl<__Provider__, __Context__> GetString<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + GetStringComponent, + >>::Delegate: GetString<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Provider__ as DelegateComponent< + GetStringComponent, + >>::Delegate::foo(__context__) + } + } + pub struct GetStringComponent; + impl<__Context__> GetString<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> &str { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> GetString<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: GetString<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + GetString<__Context__>, + {} + impl<__Context__> GetString<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(__context__: &__Context__) -> &str { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_str() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + {} + impl<__Context__, __Tag__> GetString<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_str() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + {} + impl<__Context__, __Provider__> GetString<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, GetStringComponent, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_str() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, GetStringComponent, Value = String>, + {} + ") + } } #[derive(HasField)] @@ -37,27 +307,163 @@ pub fn test_string_getter_with_custom_name() { pub bar: String, } - delegate_components! { - App { - GetStringComponent: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + GetStringComponent: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { - bar: "abc".to_owned(), - }; + #[test] + pub fn test_string_getter_with_custom_name() { + let context = App { + bar: "abc".to_owned(), + }; - assert_eq!(context.foo(), "abc"); + assert_eq!(context.foo(), "abc"); + } } -#[test] -pub fn test_string_getter_with_custom_spec() { - #[cgp_getter{ - provider: GetString, - name: GetStringComp, - }] - pub trait HasFoo { - fn foo(&self) -> &str; +mod string_getter_with_custom_spec { + use cgp::prelude::*; + use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_delegate_components}; + + snapshot_cgp_getter! { + #[cgp_getter{ + provider: GetString, + name: GetStringComp, + }] + pub trait HasFoo { + fn foo(&self) -> &str; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &str; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: GetString<__Context__>, + { + fn foo(&self) -> &str { + __Context__::foo(self) + } + } + pub trait GetString<__Context__>: IsProviderFor { + fn foo(__context__: &__Context__) -> &str; + } + impl<__Provider__, __Context__> GetString<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent>::Delegate: GetString<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Provider__ as DelegateComponent>::Delegate::foo(__context__) + } + } + pub struct GetStringComp; + impl<__Context__> GetString<__Context__> for UseContext + where + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> &str { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> GetString<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: GetString<__Context__>, + { + fn foo(__context__: &__Context__) -> &str { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl<__Context__, __Components__, __Path__> IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + GetString<__Context__>, + {} + impl<__Context__> GetString<__Context__> for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(__context__: &__Context__) -> &str { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_str() + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + {} + impl<__Context__, __Tag__> GetString<__Context__> for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __context__.get_field(::core::marker::PhantomData::<__Tag__>).as_str() + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasField<__Tag__, Value = String>, + {} + impl<__Context__, __Provider__> GetString<__Context__> for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, GetStringComp, Value = String>, + { + fn foo(__context__: &__Context__) -> &str { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + .as_str() + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Provider__: FieldGetter<__Context__, GetStringComp, Value = String>, + {} + ") + } } #[derive(HasField)] @@ -65,24 +471,70 @@ pub fn test_string_getter_with_custom_spec() { pub bar: String, } - delegate_components! { - App { - GetStringComp: UseField, + snapshot_delegate_components! { + delegate_components! { + App { + GetStringComp: UseField, + } + } + + expand_app(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for App { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for App + where + UseField: IsProviderFor, + {} + "#) } } - let context = App { - bar: "abc".to_owned(), - }; + #[test] + pub fn test_string_getter_with_custom_spec() { + let context = App { + bar: "abc".to_owned(), + }; - assert_eq!(context.foo(), "abc"); + assert_eq!(context.foo(), "abc"); + } } -#[test] -pub fn test_string_auto_getter() { - #[cgp_auto_getter] - pub trait HasFoo { - fn foo(&self) -> &str; +mod string_auto_getter { + use cgp::prelude::*; + use cgp_macro_test_util::snapshot_cgp_auto_getter; + + snapshot_cgp_auto_getter! { + #[cgp_auto_getter] + pub trait HasFoo { + fn foo(&self) -> &str; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo { + fn foo(&self) -> &str; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = String, + >, + { + fn foo(&self) -> &str { + self.get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + .as_str() + } + } + ") + } } #[derive(HasField)] @@ -90,9 +542,12 @@ pub fn test_string_auto_getter() { pub foo: String, } - let context = App { - foo: "abc".to_owned(), - }; + #[test] + pub fn test_string_auto_getter() { + let context = App { + foo: "abc".to_owned(), + }; - assert_eq!(context.foo(), "abc"); + assert_eq!(context.foo(), "abc"); + } } diff --git a/crates/tests/cgp-tests/tests/handler_tests/computer_macro.rs b/crates/tests/cgp-tests/tests/handler_tests/computer_macro.rs index 93a21701..deb06236 100644 --- a/crates/tests/cgp-tests/tests/handler_tests/computer_macro.rs +++ b/crates/tests/cgp-tests/tests/handler_tests/computer_macro.rs @@ -4,6 +4,7 @@ use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::extra::error::RaiseFrom; use cgp::extra::handler::{ComputerRef, HandlerRef, TryComputerRef}; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; use futures::executor::block_on; #[cgp_computer] @@ -18,12 +19,39 @@ fn add_with_error(a: u64, b: u64) -> Result { pub struct App; -delegate_components! { - App { - ErrorTypeProviderComponent: - UseType, - ErrorRaiserComponent: - RaiseFrom, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: + UseType, + ErrorRaiserComponent: + RaiseFrom, + } + } + + expand_computer_macro_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = RaiseFrom; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + RaiseFrom: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/handler_tests/handler_macro.rs b/crates/tests/cgp-tests/tests/handler_tests/handler_macro.rs index 0e87d358..b693cab6 100644 --- a/crates/tests/cgp-tests/tests/handler_tests/handler_macro.rs +++ b/crates/tests/cgp-tests/tests/handler_tests/handler_macro.rs @@ -4,6 +4,7 @@ use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::extra::error::RaiseFrom; use cgp::extra::handler::HandlerRef; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; use futures::executor::block_on; #[cgp_computer] @@ -18,12 +19,39 @@ async fn add_with_error(a: u64, b: u64) -> Result { pub struct App; -delegate_components! { - App { - ErrorTypeProviderComponent: - UseType, - ErrorRaiserComponent: - RaiseFrom, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: + UseType, + ErrorRaiserComponent: + RaiseFrom, + } + } + + expand_handler_macro_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = RaiseFrom; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + RaiseFrom: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/handler_tests/pipe.rs b/crates/tests/cgp-tests/tests/handler_tests/pipe.rs index 29fb2a97..23765c1a 100644 --- a/crates/tests/cgp-tests/tests/handler_tests/pipe.rs +++ b/crates/tests/cgp-tests/tests/handler_tests/pipe.rs @@ -1,37 +1,77 @@ -use core::convert::Infallible; -use core::marker::PhantomData; - -use cgp::core::error::ErrorTypeProviderComponent; -use cgp::extra::handler::{ - CanCompute, CanHandle, Computer, ComputerComponent, Handler, HandlerComponent, PipeHandlers, - Promote, PromoteAsync, -}; -use cgp::prelude::*; -use futures::executor::block_on; - -#[test] -pub fn test_pipe_computers() { - #[cgp_new_provider] - impl Computer for Multiply - where - Context: HasField, - { - type Output = u64; - - fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { - input * context.get_field(PhantomData) +mod pipe_computers { + use core::marker::PhantomData; + + use cgp::extra::handler::{CanCompute, Computer, ComputerComponent, PipeHandlers}; + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_new_provider, snapshot_check_components, snapshot_delegate_components, + }; + + snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Computer for Multiply + where + Context: HasField, + { + type Output = u64; + + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input * context.get_field(PhantomData) + } + } + + expand_multiply(output) { + insta::assert_snapshot!(output, @" + impl Computer for Multiply + where + Context: HasField, + { + type Output = u64; + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input * context.get_field(PhantomData) + } + } + impl IsProviderFor + for Multiply + where + Context: HasField, + {} + pub struct Multiply(pub ::core::marker::PhantomData<(Field)>); + ") } } - #[cgp_new_provider] - impl Computer for Add - where - Context: HasField, - { - type Output = u64; + snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Computer for Add + where + Context: HasField, + { + type Output = u64; + + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input + context.get_field(PhantomData) + } + } - fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { - input + context.get_field(PhantomData) + expand_add(output) { + insta::assert_snapshot!(output, @" + impl Computer for Add + where + Context: HasField, + { + type Output = u64; + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input + context.get_field(PhantomData) + } + } + impl IsProviderFor + for Add + where + Context: HasField, + {} + pub struct Add(pub ::core::marker::PhantomData<(Field)>); + ") } } @@ -42,64 +82,164 @@ pub fn test_pipe_computers() { pub baz: u64, } - delegate_components! { - MyContext { - ComputerComponent: + snapshot_delegate_components! { + delegate_components! { + MyContext { + ComputerComponent: + PipeHandlers< + Product! [ + Multiply, + Add, + Multiply, + ] + >, + } + } + + expand_pipe_computers(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = PipeHandlers< + Product![ + Multiply < Symbol!("foo") >, Add < Symbol!("bar") >, Multiply < + Symbol!("baz") >, + ], + >; + } + impl<__Context__, __Params__> IsProviderFor + for MyContext + where PipeHandlers< - Product! [ - Multiply, - Add, - Multiply, - ] - >, + Product![ + Multiply < Symbol!("foo") >, Add < Symbol!("bar") >, Multiply < + Symbol!("baz") >, + ], + >: IsProviderFor, + {} + "#) } } - check_components! { - - MyContext { - ComputerComponent: (Tag, u64), + snapshot_check_components! { + check_components! { + + MyContext { + ComputerComponent: (Tag, u64), + } + } + + expand_check_pipe_computers(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + ") } } - let context = MyContext { - foo: 2, - bar: 3, - baz: 4, - }; + #[test] + pub fn test_pipe_computers() { + let context = MyContext { + foo: 2, + bar: 3, + baz: 4, + }; - let result = context.compute(PhantomData::<()>, 5); + let result = context.compute(PhantomData::<()>, 5); - assert_eq!(result, ((5 * 2) + 3) * 4); + assert_eq!(result, ((5 * 2) + 3) * 4); + } } -#[test] -pub fn test_pipe_handlers() { - #[cgp_new_provider] - impl Handler for Multiply - where - Context: HasErrorType + HasField, - { - type Output = u64; - - async fn handle( - context: &Context, - _tag: PhantomData, - input: u64, - ) -> Result { - Ok(input * context.get_field(PhantomData)) +mod pipe_handlers { + use core::convert::Infallible; + use core::marker::PhantomData; + + use cgp::core::error::ErrorTypeProviderComponent; + use cgp::extra::handler::{ + CanHandle, Computer, Handler, HandlerComponent, PipeHandlers, Promote, PromoteAsync, + }; + use cgp::prelude::*; + use cgp_macro_test_util::{ + snapshot_cgp_new_provider, snapshot_check_components, snapshot_delegate_components, + }; + use futures::executor::block_on; + + snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Handler for Multiply + where + Context: HasErrorType + HasField, + { + type Output = u64; + + async fn handle( + context: &Context, + _tag: PhantomData, + input: u64, + ) -> Result { + Ok(input * context.get_field(PhantomData)) + } + } + + expand_multiply(output) { + insta::assert_snapshot!(output, @" + impl Handler for Multiply + where + Context: HasErrorType + HasField, + { + type Output = u64; + async fn handle( + context: &Context, + _tag: PhantomData, + input: u64, + ) -> Result { + Ok(input * context.get_field(PhantomData)) + } + } + impl IsProviderFor + for Multiply + where + Context: HasErrorType + HasField, + {} + pub struct Multiply(pub ::core::marker::PhantomData<(Field)>); + ") } } - #[cgp_new_provider] - impl Computer for Add - where - Context: HasField, - { - type Output = u64; + snapshot_cgp_new_provider! { + #[cgp_new_provider] + impl Computer for Add + where + Context: HasField, + { + type Output = u64; + + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input + context.get_field(PhantomData) + } + } - fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { - input + context.get_field(PhantomData) + expand_add(output) { + insta::assert_snapshot!(output, @" + impl Computer for Add + where + Context: HasField, + { + type Output = u64; + fn compute(context: &Context, _tag: PhantomData, input: u64) -> u64 { + input + context.get_field(PhantomData) + } + } + impl IsProviderFor + for Add + where + Context: HasField, + {} + pub struct Add(pub ::core::marker::PhantomData<(Field)>); + ") } } @@ -110,34 +250,86 @@ pub fn test_pipe_handlers() { pub baz: u64, } - delegate_components! { - MyContext { - ErrorTypeProviderComponent: UseType, - HandlerComponent: + snapshot_delegate_components! { + delegate_components! { + MyContext { + ErrorTypeProviderComponent: UseType, + HandlerComponent: + PipeHandlers< + Product! [ + Multiply, + PromoteAsync>>, + Multiply, + ] + >, + } + } + + expand_pipe_handlers(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseType< + Infallible, + >: IsProviderFor, + {} + impl DelegateComponent for MyContext { + type Delegate = PipeHandlers< + Product![ + Multiply < Symbol!("foo") >, PromoteAsync < Promote < Add < Symbol!("bar") + >>>, Multiply < Symbol!("baz") >, + ], + >; + } + impl<__Context__, __Params__> IsProviderFor + for MyContext + where PipeHandlers< - Product! [ - Multiply, - PromoteAsync>>, - Multiply, - ] - >, + Product![ + Multiply < Symbol!("foo") >, PromoteAsync < Promote < Add < Symbol!("bar") + >>>, Multiply < Symbol!("baz") >, + ], + >: IsProviderFor, + {} + "#) } } - check_components! { - - MyContext { - HandlerComponent: (Tag, u64), + snapshot_check_components! { + check_components! { + + MyContext { + HandlerComponent: (Tag, u64), + } + } + + expand_check_pipe_handlers(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + ") } } - let context = MyContext { - foo: 2, - bar: 3, - baz: 4, - }; + #[test] + pub fn test_pipe_handlers() { + let context = MyContext { + foo: 2, + bar: 3, + baz: 4, + }; - let result = block_on(context.handle(PhantomData::<()>, 5)).unwrap(); + let result = block_on(context.handle(PhantomData::<()>, 5)).unwrap(); - assert_eq!(result, ((5 * 2) + 3) * 4); + assert_eq!(result, ((5 * 2) + 3) * 4); + } } diff --git a/crates/tests/cgp-tests/tests/handler_tests/producer_macro.rs b/crates/tests/cgp-tests/tests/handler_tests/producer_macro.rs index e913b75a..b256e0ba 100644 --- a/crates/tests/cgp-tests/tests/handler_tests/producer_macro.rs +++ b/crates/tests/cgp-tests/tests/handler_tests/producer_macro.rs @@ -1,6 +1,7 @@ use cgp::core::error::ErrorTypeProviderComponent; use cgp::extra::handler::{ComputerRef, HandlerRef, TryComputerRef}; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; use futures::executor::block_on; #[cgp_producer] @@ -10,10 +11,27 @@ pub fn magic_number() -> u64 { pub struct App; -delegate_components! { - App { - ErrorTypeProviderComponent: - UseType, +snapshot_delegate_components! { + delegate_components! { + App { + ErrorTypeProviderComponent: + UseType, + } + } + + expand_producer_macro_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + UseType: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/multi_param.rs b/crates/tests/cgp-tests/tests/namespace_tests/multi_param.rs index 3c2ddfb1..436d082e 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/multi_param.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/multi_param.rs @@ -1,58 +1,366 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_check_components, + snapshot_delegate_components, +}; -#[cgp_component(FooProvider)] -#[prefix(@app in DefaultNamespace)] -pub trait Foo<'a, T, U> { - fn foo(&self, first: &'a T, second: U); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + #[prefix(@app in DefaultNamespace)] + pub trait Foo<'a, T, U> { + fn foo(&self, first: &'a T, second: U); + } + + expand_multi_param_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo<'a, T, U> { + fn foo(&self, first: &'a T, second: U); + } + impl<'a, __Context__, T, U> Foo<'a, T, U> for __Context__ + where + __Context__: FooProvider<'a, __Context__, T, U>, + { + fn foo(&self, first: &'a T, second: U) { + __Context__::foo(self, first, second) + } + } + pub trait FooProvider< + 'a, + __Context__, + T, + U, + >: IsProviderFor, T, U)> { + fn foo(__context__: &__Context__, first: &'a T, second: U); + } + impl<'a, __Provider__, __Context__, T, U> FooProvider<'a, __Context__, T, U> + for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, T, U)>, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<'a, __Context__, T, U>, + { + fn foo(__context__: &__Context__, first: &'a T, second: U) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__, first, second) + } + } + pub struct FooProviderComponent; + impl<'a, __Context__, T, U> FooProvider<'a, __Context__, T, U> for UseContext + where + __Context__: Foo<'a, T, U>, + { + fn foo(__context__: &__Context__, first: &'a T, second: U) { + __Context__::foo(__context__, first, second) + } + } + impl< + 'a, + __Context__, + T, + U, + > IsProviderFor, T, U)> for UseContext + where + __Context__: Foo<'a, T, U>, + {} + impl<'a, __Context__, T, U, __Components__, __Path__> FooProvider<'a, __Context__, T, U> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: FooProvider<'a, __Context__, T, U>, + { + fn foo(__context__: &__Context__, first: &'a T, second: U) { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate::foo(__context__, first, second) + } + } + impl< + 'a, + __Context__, + T, + U, + __Components__, + __Path__, + > IsProviderFor, T, U)> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>>::Output, + >>::Delegate: FooProvider<'a, __Context__, T, U>, + {} + impl<__Components__> DefaultNamespace<__Components__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + >; + } + ") + } } -#[cgp_impl(new DummyFoo)] -impl<'a, T, U> FooProvider<'a, T, U> { - fn foo(&self, _first: &'a T, _second: U) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl<'a, T, U> FooProvider<'a, T, U> { + fn foo(&self, _first: &'a T, _second: U) {} + } + + expand_multi_param_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<'a, __Context__, T, U> FooProvider<'a, __Context__, T, U> for DummyFoo { + fn foo(__context__: &__Context__, _first: &'a T, _second: U) {} + } + impl< + 'a, + __Context__, + T, + U, + > IsProviderFor, T, U)> for DummyFoo {} + pub struct DummyFoo; + ") + } } pub struct AppA; -delegate_components! { - AppA { - open {FooProviderComponent}; +snapshot_delegate_components! { + delegate_components! { + AppA { + open {FooProviderComponent}; + + @FooProviderComponent.String.u32: + DummyFoo, + @FooProviderComponent.bool.T: + DummyFoo, + } + } - @FooProviderComponent.String.u32: - DummyFoo, - @FooProviderComponent.bool.T: - DummyFoo, + expand_multi_param_app_a(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for AppA { + type Delegate = RedirectLookup>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for AppA + where + RedirectLookup< + AppA, + PathCons, + >: IsProviderFor, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons>>, + > for AppA { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>>, + __Context__, + __Params__, + > for AppA + where + DummyFoo: IsProviderFor< + PathCons>>, + __Context__, + __Params__, + >, + {} + impl< + T, + __Wildcard__, + > DelegateComponent< + PathCons>>, + > for AppA { + type Delegate = DummyFoo; + } + impl< + T, + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>>, + __Context__, + __Params__, + > for AppA + where + DummyFoo: IsProviderFor< + PathCons>>, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - AppA { - FooProviderComponent: [ - <'a> (Life<'a>, String, u32), - <'a> (Life<'a>, bool, String), - ], - FooProviderComponent: - <'a> (Life<'a>, bool, bool), +snapshot_check_components! { + check_components! { + AppA { + FooProviderComponent: [ + <'a> (Life<'a>, String, u32), + <'a> (Life<'a>, bool, String), + ], + FooProviderComponent: + <'a> (Life<'a>, bool, bool), + } + } + + expand_check_app_a(output) { + insta::assert_snapshot!(output, @" + trait __CheckAppA< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl<'a> __CheckAppA, String, u32)> for AppA {} + impl<'a> __CheckAppA, bool, String)> for AppA {} + impl<'a> __CheckAppA, bool, bool)> for AppA {} + ") } } pub struct AppB; -delegate_components! { - AppB { - namespace DefaultNamespace; +snapshot_delegate_components! { + delegate_components! { + AppB { + namespace DefaultNamespace; - @app.FooProviderComponent.String.u64: - DummyFoo, - @app.FooProviderComponent.bool. T: - DummyFoo, + @app.FooProviderComponent.String.u64: + DummyFoo, + @app.FooProviderComponent.bool. T: + DummyFoo, + } + } + + expand_multi_param_app_b(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for AppB + where + __Key__: DefaultNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for AppB + where + __Key__: DefaultNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + > for AppB { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + __Context__, + __Params__, + > for AppB + where + DummyFoo: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + __Context__, + __Params__, + >, + {} + impl< + T, + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + > for AppB { + type Delegate = DummyFoo; + } + impl< + T, + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + __Context__, + __Params__, + > for AppB + where + DummyFoo: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>>, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - <'a> AppB { - FooProviderComponent: [ - (Life<'a>, String, u64), - (Life<'a>, bool, String), - ], +snapshot_check_components! { + check_components! { + <'a> AppB { + FooProviderComponent: [ + (Life<'a>, String, u64), + (Life<'a>, bool, String), + ], + } + } + + expand_check_app_b(output) { + insta::assert_snapshot!(output, @" + trait __CheckAppB< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl<'a> __CheckAppB, String, u64)> for AppB {} + impl<'a> __CheckAppB, bool, String)> for AppB {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace.rs index 0742ec6e..96f69787 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace.rs @@ -1,30 +1,273 @@ use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::extra::error::ReturnError; use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_check_components, snapshot_delegate_components, +}; pub struct MyComponents; -#[cgp_component(FooProvider)] -#[prefix(@app.MyComponents.FooProviderComponent in DefaultNamespace)] -pub trait Foo { - fn foo(&self); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + #[prefix(@app.MyComponents.FooProviderComponent in DefaultNamespace)] + pub trait Foo { + fn foo(&self); + } + + expand_namespace_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self); + } + impl<__Context__> Foo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self) { + __Context__::foo(self) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__) { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + impl<__Components__> DefaultNamespace<__Components__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons< + MyComponents, + PathCons>, + >, + >, + >; + } + ") + } } pub struct App; -delegate_components! { - App { - namespace DefaultNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace DefaultNamespace; - @cgp.core.error.ErrorTypeProviderComponent: - UseType, - @cgp.core.error.ErrorRaiserComponent.String: - ReturnError, + @cgp.core.error.ErrorTypeProviderComponent: + UseType, + @cgp.core.error.ErrorRaiserComponent.String: + ReturnError, + } + } + + expand_namespace_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: DefaultNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: DefaultNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons, + >, + >, + >, + > for App { + type Delegate = UseType; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons, + >, + >, + >, + __Context__, + __Params__, + > for App + where + UseType< + String, + >: IsProviderFor< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons, + >, + >, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons>, + >, + >, + >, + > for App { + type Delegate = ReturnError; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons>, + >, + >, + >, + __Context__, + __Params__, + > for App + where + ReturnError: IsProviderFor< + PathCons< + Symbol<3, Chars<'c', Chars<'g', Chars<'p', Nil>>>>, + PathCons< + Symbol<4, Chars<'c', Chars<'o', Chars<'r', Chars<'e', Nil>>>>>, + PathCons< + Symbol< + 5, + Chars<'e', Chars<'r', Chars<'r', Chars<'o', Chars<'r', Nil>>>>>, + >, + PathCons>, + >, + >, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - ErrorRaiserComponent: String, +snapshot_check_components! { + check_components! { + App { + ErrorRaiserComponent: String, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs index ab0aac0c..55f4813e 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/basic.rs @@ -1,52 +1,311 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_cgp_namespace, snapshot_check_components, + snapshot_delegate_components, +}; -#[cgp_component(FooProvider)] -pub trait Foo { - fn foo(&self); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait Foo { + fn foo(&self); + } + + expand_basic_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self); + } + impl<__Context__> Foo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self) { + __Context__::foo(self) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__) { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + ") + } } -cgp_namespace! { - new MyNamespace { - FooProviderComponent => - @MyFooComponent, +snapshot_cgp_namespace! { + cgp_namespace! { + new MyNamespace { + FooProviderComponent => + @MyFooComponent, + } + } + + expand_basic_my_namespace(output) { + insta::assert_snapshot!(output, @" + pub trait MyNamespace<__Table__> { + type Delegate; + } + impl<__Table__> MyNamespace<__Table__> for FooProviderComponent { + type Delegate = RedirectLookup<__Table__, PathCons>; + } + ") } } -#[cgp_component(BarProvider)] -#[prefix(@MyBarComponent in MyNamespace)] -pub trait Bar { - fn bar(&self); +snapshot_cgp_component! { + #[cgp_component(BarProvider)] + #[prefix(@MyBarComponent in MyNamespace)] + pub trait Bar { + fn bar(&self); + } + + expand_basic_bar(output) { + insta::assert_snapshot!(output, @" + pub trait Bar { + fn bar(&self); + } + impl<__Context__> Bar for __Context__ + where + __Context__: BarProvider<__Context__>, + { + fn bar(&self) { + __Context__::bar(self) + } + } + pub trait BarProvider< + __Context__, + >: IsProviderFor { + fn bar(__context__: &__Context__); + } + impl<__Provider__, __Context__> BarProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarProviderComponent; + impl<__Context__> BarProvider<__Context__> for UseContext + where + __Context__: Bar, + { + fn bar(__context__: &__Context__) { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Bar, + {} + impl<__Context__, __Components__, __Path__> BarProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarProvider<__Context__>, + {} + impl<__Components__> MyNamespace<__Components__> for BarProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons>, + >; + } + ") + } } pub struct MyFooComponent; pub struct MyBarComponent; -#[cgp_impl(new DummyFoo)] -impl FooProvider { - fn foo(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl FooProvider { + fn foo(&self) {} + } + + expand_basic_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> FooProvider<__Context__> for DummyFoo { + fn foo(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyFoo {} + pub struct DummyFoo; + ") + } } -#[cgp_impl(new DummyBar)] -impl BarProvider { - fn bar(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyBar)] + impl BarProvider { + fn bar(&self) {} + } + + expand_basic_dummy_bar(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> BarProvider<__Context__> for DummyBar { + fn bar(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyBar {} + pub struct DummyBar; + ") + } } pub struct App; -delegate_components! { - App { - namespace MyNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace MyNamespace; - @MyFooComponent: - DummyFoo, - @MyBarComponent: - DummyBar, + @MyFooComponent: + DummyFoo, + @MyBarComponent: + DummyBar, + } + } + + expand_basic_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: MyNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: MyNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl<__Wildcard__> DelegateComponent> for App { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for App + where + DummyFoo: IsProviderFor< + PathCons, + __Context__, + __Params__, + >, + {} + impl<__Wildcard__> DelegateComponent> for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor, __Context__, __Params__> for App + where + DummyBar: IsProviderFor< + PathCons, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent, - BarProviderComponent, +snapshot_check_components! { + check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs index dabdc5c9..c801a4cb 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/default_impls.rs @@ -1,75 +1,369 @@ use cgp::core::component::DefaultImpls1; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_components}; use cgp_tests::namespaces::default_impls::{ DefaultShowComponents, ExtendedNamespace, ShowImplComponent, ShowWithDisplay, }; pub struct AppA; -delegate_components! { - AppA { - namespace DefaultNamespace; +snapshot_delegate_components! { + delegate_components! { + AppA { + namespace DefaultNamespace; - for in DefaultImpls1 { - @test.ShowImplComponent.T: Provider, + for in DefaultImpls1 { + @test.ShowImplComponent.T: Provider, + } + + @test.ShowImplComponent.u64: + ShowWithDisplay, } + } - @test.ShowImplComponent.u64: - ShowWithDisplay, + expand_default_impls_app_a(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for AppA + where + __Key__: DefaultNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for AppA + where + __Key__: DefaultNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + T, + Provider, + > DelegateComponent< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + > for AppA + where + T: DefaultImpls1, + { + type Delegate = Provider; + } + impl< + __Wildcard__, + T, + Provider, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for AppA + where + T: DefaultImpls1, + Provider: IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + > for AppA { + type Delegate = ShowWithDisplay; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for AppA + where + ShowWithDisplay: IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - AppA { - ShowImplComponent: [ - String, - u64, - ] +snapshot_check_components! { + check_components! { + AppA { + ShowImplComponent: [ + String, + u64, + ] + } + } + + expand_check_app_a(output) { + insta::assert_snapshot!(output, @" + trait __CheckAppA< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckAppA for AppA {} + impl __CheckAppA for AppA {} + ") } } pub struct AppB; -delegate_components! { - AppB { - namespace DefaultNamespace; +snapshot_delegate_components! { + delegate_components! { + AppB { + namespace DefaultNamespace; + + for in DefaultShowComponents { + @test.ShowImplComponent.T: Provider, + } + } + } - for in DefaultShowComponents { - @test.ShowImplComponent.T: Provider, + expand_default_impls_app_b(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for AppB + where + __Key__: DefaultNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for AppB + where + __Key__: DefaultNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + T, + Provider, + > DelegateComponent< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + > for AppB + where + T: DefaultShowComponents, + { + type Delegate = Provider; } + impl< + __Wildcard__, + T, + Provider, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for AppB + where + T: DefaultShowComponents, + Provider: IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - AppB { - ShowImplComponent: [ - String, - u64, - ] +snapshot_check_components! { + check_components! { + AppB { + ShowImplComponent: [ + String, + u64, + ] + } + } + + expand_check_app_b(output) { + insta::assert_snapshot!(output, @" + trait __CheckAppB< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckAppB for AppB {} + impl __CheckAppB for AppB {} + ") } } pub struct AppC; -delegate_components! { - AppC { - namespace ExtendedNamespace; +snapshot_delegate_components! { + delegate_components! { + AppC { + namespace ExtendedNamespace; - for in DefaultImpls1 { - @test.ShowImplComponent.T: Provider, + for in DefaultImpls1 { + @test.ShowImplComponent.T: Provider, + } + + @test.ShowImplComponent.u64: + ShowWithDisplay, } + } - @test.ShowImplComponent.u64: - ShowWithDisplay, + expand_default_impls_app_c(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for AppC + where + __Key__: ExtendedNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for AppC + where + __Key__: ExtendedNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + T, + Provider, + > DelegateComponent< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + > for AppC + where + T: DefaultImpls1, + { + type Delegate = Provider; + } + impl< + __Wildcard__, + T, + Provider, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for AppC + where + T: DefaultImpls1, + Provider: IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + > for AppC { + type Delegate = ShowWithDisplay; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for AppC + where + ShowWithDisplay: IsProviderFor< + PathCons< + Symbol<4, Chars<'t', Chars<'e', Chars<'s', Chars<'t', Nil>>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - AppC { - ShowImplComponent: [ - String, - u64, - u32, - ] +snapshot_check_components! { + check_components! { + AppC { + ShowImplComponent: [ + String, + u64, + u32, + ] + } + } + + expand_check_app_c(output) { + insta::assert_snapshot!(output, @" + trait __CheckAppC< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckAppC for AppC {} + impl __CheckAppC for AppC {} + impl __CheckAppC for AppC {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs index 64d08afb..7d067728 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/extended_namespace.rs @@ -2,23 +2,187 @@ use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent, ErrorWr use cgp::extra::error::RaiseFrom; use cgp::extra::handler::CanTryCompute; use cgp::prelude::*; +use cgp_macro_test_util::snapshot_delegate_components; use cgp_tests::namespaces::extended::ExtendedNamespace; pub struct App; -delegate_components! { - App { - namespace ExtendedNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace ExtendedNamespace; - @app.ErrorTypeProviderComponent: - UseType, - @app.{ - ErrorRaiserComponent.{&'static str, String}, - ErrorWrapperComponent, - }: - RaiseFrom, - TryComputerComponent: - Foo, + @app.ErrorTypeProviderComponent: + UseType, + @app.{ + ErrorRaiserComponent.{&'static str, String}, + ErrorWrapperComponent, + }: + RaiseFrom, + TryComputerComponent: + Foo, + } + } + + expand_extended_ns_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: ExtendedNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: ExtendedNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + > for App { + type Delegate = UseType; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + __Context__, + __Params__, + > for App + where + UseType< + String, + >: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + > for App { + type Delegate = RaiseFrom; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for App + where + RaiseFrom: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + > for App { + type Delegate = RaiseFrom; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + __Context__, + __Params__, + > for App + where + RaiseFrom: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons>, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + > for App { + type Delegate = RaiseFrom; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + __Context__, + __Params__, + > for App + where + RaiseFrom: IsProviderFor< + PathCons< + Symbol<3, Chars<'a', Chars<'p', Chars<'p', Nil>>>>, + PathCons, + >, + __Context__, + __Params__, + >, + {} + impl DelegateComponent for App { + type Delegate = Foo; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + Foo: IsProviderFor, + {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs index 4425feb0..77d4e9ac 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/multi_namespace.rs @@ -1,83 +1,521 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_cgp_namespace, snapshot_check_components, + snapshot_delegate_components, +}; pub struct MyApp; -#[cgp_component(FooProvider)] -pub trait Foo { - fn foo(&self); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait Foo { + fn foo(&self); + } + + expand_multi_ns_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self); + } + impl<__Context__> Foo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self) { + __Context__::foo(self) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__) { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + ") + } } -cgp_namespace! { - new MyNamespace { - FooProviderComponent => - @MyApp.MyFooComponent, +snapshot_cgp_namespace! { + cgp_namespace! { + new MyNamespace { + FooProviderComponent => + @MyApp.MyFooComponent, + } + } + + expand_multi_ns_my_namespace(output) { + insta::assert_snapshot!(output, @" + pub trait MyNamespace<__Table__> { + type Delegate; + } + impl<__Table__> MyNamespace<__Table__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Table__, + PathCons>, + >; + } + ") } } -cgp_namespace! { - new OtherNamespace { - FooProviderComponent => - @my_app.MyFooComponent, +snapshot_cgp_namespace! { + cgp_namespace! { + new OtherNamespace { + FooProviderComponent => + @my_app.MyFooComponent, + } + } + + expand_multi_ns_other_namespace(output) { + insta::assert_snapshot!(output, @" + pub trait OtherNamespace<__Table__> { + type Delegate; + } + impl<__Table__> OtherNamespace<__Table__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Table__, + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + >; + } + ") } } -#[cgp_component(BarProvider)] -#[prefix(@MyApp.MyBarComponent in MyNamespace)] -#[prefix(@my_app.MyBarComponent in OtherNamespace)] -pub trait Bar { - fn bar(&self); +snapshot_cgp_component! { + #[cgp_component(BarProvider)] + #[prefix(@MyApp.MyBarComponent in MyNamespace)] + #[prefix(@my_app.MyBarComponent in OtherNamespace)] + pub trait Bar { + fn bar(&self); + } + + expand_multi_ns_bar(output) { + insta::assert_snapshot!(output, @" + pub trait Bar { + fn bar(&self); + } + impl<__Context__> Bar for __Context__ + where + __Context__: BarProvider<__Context__>, + { + fn bar(&self) { + __Context__::bar(self) + } + } + pub trait BarProvider< + __Context__, + >: IsProviderFor { + fn bar(__context__: &__Context__); + } + impl<__Provider__, __Context__> BarProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarProviderComponent; + impl<__Context__> BarProvider<__Context__> for UseContext + where + __Context__: Bar, + { + fn bar(__context__: &__Context__) { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Bar, + {} + impl<__Context__, __Components__, __Path__> BarProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarProvider<__Context__>, + {} + impl<__Components__> MyNamespace<__Components__> for BarProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons>>, + >; + } + impl<__Components__> OtherNamespace<__Components__> for BarProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons>, + >, + >; + } + ") + } } pub struct MyFooComponent; pub struct MyBarComponent; -#[cgp_impl(new DummyFoo)] -impl FooProvider { - fn foo(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl FooProvider { + fn foo(&self) {} + } + + expand_multi_ns_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> FooProvider<__Context__> for DummyFoo { + fn foo(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyFoo {} + pub struct DummyFoo; + ") + } } -#[cgp_impl(new DummyBar)] -impl BarProvider { - fn bar(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyBar)] + impl BarProvider { + fn bar(&self) {} + } + + expand_multi_ns_dummy_bar(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> BarProvider<__Context__> for DummyBar { + fn bar(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyBar {} + pub struct DummyBar; + ") + } } pub struct App; -delegate_components! { - App { - namespace MyNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace MyNamespace; + + @MyApp.MyFooComponent: + DummyFoo, + @MyApp.MyBarComponent: + DummyBar, + } + } - @MyApp.MyFooComponent: - DummyFoo, - @MyApp.MyBarComponent: - DummyBar, + expand_multi_ns_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: MyNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: MyNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent>> for App { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyFoo: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent, - BarProviderComponent, +snapshot_check_components! { + check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } pub struct OtherApp; -delegate_components! { - OtherApp { - namespace OtherNamespace; +snapshot_delegate_components! { + delegate_components! { + OtherApp { + namespace OtherNamespace; + + @my_app.MyFooComponent: + DummyFoo, + @my_app.MyBarComponent: + DummyBar, + } + } - @my_app.MyFooComponent: - DummyFoo, - @my_app.MyBarComponent: - DummyBar, + expand_multi_ns_other_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for OtherApp + where + __Key__: OtherNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for OtherApp + where + __Key__: OtherNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + > for OtherApp { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + __Context__, + __Params__, + > for OtherApp + where + DummyFoo: IsProviderFor< + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + > for OtherApp { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + __Context__, + __Params__, + > for OtherApp + where + DummyBar: IsProviderFor< + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - OtherApp { - FooProviderComponent, - BarProviderComponent, +snapshot_check_components! { + check_components! { + OtherApp { + FooProviderComponent, + BarProviderComponent, + } + } + + expand_check_other_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckOtherApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckOtherApp for OtherApp {} + impl __CheckOtherApp for OtherApp {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs index e781932c..c398d71a 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/symbol_path.rs @@ -1,53 +1,391 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_cgp_namespace, snapshot_check_components, + snapshot_delegate_components, +}; -#[cgp_component(FooProvider)] -pub trait Foo { - fn foo(&self); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait Foo { + fn foo(&self); + } + + expand_symbol_path_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self); + } + impl<__Context__> Foo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self) { + __Context__::foo(self) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__) { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + ") + } } -cgp_namespace! { - new MyNamespace { - FooProviderComponent => - @my_app.MyFooComponent, +snapshot_cgp_namespace! { + cgp_namespace! { + new MyNamespace { + FooProviderComponent => + @my_app.MyFooComponent, + } + } + + expand_symbol_path_my_namespace(output) { + insta::assert_snapshot!(output, @" + pub trait MyNamespace<__Table__> { + type Delegate; + } + impl<__Table__> MyNamespace<__Table__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Table__, + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + >; + } + ") } } -#[cgp_component(BarProvider)] -#[prefix(@my_app.MyBarComponent in MyNamespace)] -pub trait Bar { - fn bar(&self); +snapshot_cgp_component! { + #[cgp_component(BarProvider)] + #[prefix(@my_app.MyBarComponent in MyNamespace)] + pub trait Bar { + fn bar(&self); + } + + expand_symbol_path_bar(output) { + insta::assert_snapshot!(output, @" + pub trait Bar { + fn bar(&self); + } + impl<__Context__> Bar for __Context__ + where + __Context__: BarProvider<__Context__>, + { + fn bar(&self) { + __Context__::bar(self) + } + } + pub trait BarProvider< + __Context__, + >: IsProviderFor { + fn bar(__context__: &__Context__); + } + impl<__Provider__, __Context__> BarProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarProviderComponent; + impl<__Context__> BarProvider<__Context__> for UseContext + where + __Context__: Bar, + { + fn bar(__context__: &__Context__) { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Bar, + {} + impl<__Context__, __Components__, __Path__> BarProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarProvider<__Context__>, + {} + impl<__Components__> MyNamespace<__Components__> for BarProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons>, + >, + >; + } + ") + } } pub struct MyFooComponent; pub struct MyBarComponent; -#[cgp_impl(new DummyFoo)] -impl FooProvider { - fn foo(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl FooProvider { + fn foo(&self) {} + } + + expand_symbol_path_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> FooProvider<__Context__> for DummyFoo { + fn foo(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyFoo {} + pub struct DummyFoo; + ") + } } -#[cgp_impl(new DummyBar)] -impl BarProvider { - fn bar(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyBar)] + impl BarProvider { + fn bar(&self) {} + } + + expand_symbol_path_dummy_bar(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> BarProvider<__Context__> for DummyBar { + fn bar(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyBar {} + pub struct DummyBar; + ") + } } pub struct App; -delegate_components! { - App { - namespace MyNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace MyNamespace; - @my_app.MyFooComponent: - DummyFoo, - @my_app.MyBarComponent: - DummyBar, + @my_app.MyFooComponent: + DummyFoo, + @my_app.MyBarComponent: + DummyBar, + } + } + + expand_symbol_path_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: MyNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: MyNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + > for App { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + __Context__, + __Params__, + > for App + where + DummyFoo: IsProviderFor< + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + > for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol< + 6, + Chars<'m', Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>>, + >, + PathCons, + >, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons< + Symbol< + 6, + Chars< + 'm', + Chars<'y', Chars<'_', Chars<'a', Chars<'p', Chars<'p', Nil>>>>>, + >, + >, + PathCons, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent, - BarProviderComponent, +snapshot_check_components! { + check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs index 0881b5f1..7704cc92 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/namespace_macro/type_path.rs @@ -1,55 +1,329 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_cgp_namespace, snapshot_check_components, + snapshot_delegate_components, +}; pub struct MyApp; -#[cgp_component(FooProvider)] -pub trait Foo { - fn foo(&self); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait Foo { + fn foo(&self); + } + + expand_type_path_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self); + } + impl<__Context__> Foo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo(&self) { + __Context__::foo(self) + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(__context__: &__Context__); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__) { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + ") + } } -cgp_namespace! { - new MyNamespace { - FooProviderComponent => - @MyApp.MyFooComponent, +snapshot_cgp_namespace! { + cgp_namespace! { + new MyNamespace { + FooProviderComponent => + @MyApp.MyFooComponent, + } + } + + expand_type_path_my_namespace(output) { + insta::assert_snapshot!(output, @" + pub trait MyNamespace<__Table__> { + type Delegate; + } + impl<__Table__> MyNamespace<__Table__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Table__, + PathCons>, + >; + } + ") } } -#[cgp_component(BarProvider)] -#[prefix(@MyApp.MyBarComponent in MyNamespace)] -pub trait Bar { - fn bar(&self); +snapshot_cgp_component! { + #[cgp_component(BarProvider)] + #[prefix(@MyApp.MyBarComponent in MyNamespace)] + pub trait Bar { + fn bar(&self); + } + + expand_type_path_bar(output) { + insta::assert_snapshot!(output, @" + pub trait Bar { + fn bar(&self); + } + impl<__Context__> Bar for __Context__ + where + __Context__: BarProvider<__Context__>, + { + fn bar(&self) { + __Context__::bar(self) + } + } + pub trait BarProvider< + __Context__, + >: IsProviderFor { + fn bar(__context__: &__Context__); + } + impl<__Provider__, __Context__> BarProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarProviderComponent; + impl<__Context__> BarProvider<__Context__> for UseContext + where + __Context__: Bar, + { + fn bar(__context__: &__Context__) { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: Bar, + {} + impl<__Context__, __Components__, __Path__> BarProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarProvider<__Context__>, + { + fn bar(__context__: &__Context__) { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarProvider<__Context__>, + {} + impl<__Components__> MyNamespace<__Components__> for BarProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons>>, + >; + } + ") + } } pub struct MyFooComponent; pub struct MyBarComponent; -#[cgp_impl(new DummyFoo)] -impl FooProvider { - fn foo(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl FooProvider { + fn foo(&self) {} + } + + expand_type_path_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> FooProvider<__Context__> for DummyFoo { + fn foo(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyFoo {} + pub struct DummyFoo; + ") + } } -#[cgp_impl(new DummyBar)] -impl BarProvider { - fn bar(&self) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyBar)] + impl BarProvider { + fn bar(&self) {} + } + + expand_type_path_dummy_bar(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> BarProvider<__Context__> for DummyBar { + fn bar(__context__: &__Context__) {} + } + impl<__Context__> IsProviderFor for DummyBar {} + pub struct DummyBar; + ") + } } pub struct App; -delegate_components! { - App { - namespace MyNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace MyNamespace; - @MyApp.MyFooComponent: - DummyFoo, - @MyApp.MyBarComponent: - DummyBar, + @MyApp.MyFooComponent: + DummyFoo, + @MyApp.MyBarComponent: + DummyBar, + } + } + + expand_type_path_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: MyNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: MyNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent>> for App { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyFoo: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent, - BarProviderComponent, +snapshot_check_components! { + check_components! { + App { + FooProviderComponent, + BarProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/open.rs b/crates/tests/cgp-tests/tests/namespace_tests/open.rs index 21c7f9cd..b7b08be2 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/open.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/open.rs @@ -1,53 +1,433 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_check_components, + snapshot_delegate_components, +}; pub struct App; -#[cgp_component(FooProvider)] -pub trait Foo { - fn foo(&self, value: &T); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + pub trait Foo { + fn foo(&self, value: &T); + } + + expand_open_foo(output) { + insta::assert_snapshot!(output, @" + pub trait Foo { + fn foo(&self, value: &T); + } + impl<__Context__, T> Foo for __Context__ + where + __Context__: FooProvider<__Context__, T>, + { + fn foo(&self, value: &T) { + __Context__::foo(self, value) + } + } + pub trait FooProvider< + __Context__, + T, + >: IsProviderFor { + fn foo(__context__: &__Context__, value: &T); + } + impl<__Provider__, __Context__, T> FooProvider<__Context__, T> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__, T>, + { + fn foo(__context__: &__Context__, value: &T) { + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate::foo(__context__, value) + } + } + pub struct FooProviderComponent; + impl<__Context__, T> FooProvider<__Context__, T> for UseContext + where + __Context__: Foo, + { + fn foo(__context__: &__Context__, value: &T) { + __Context__::foo(__context__, value) + } + } + impl<__Context__, T> IsProviderFor for UseContext + where + __Context__: Foo, + {} + impl<__Context__, T, __Components__, __Path__> FooProvider<__Context__, T> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: FooProvider<__Context__, T>, + { + fn foo(__context__: &__Context__, value: &T) { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::foo(__context__, value) + } + } + impl< + __Context__, + T, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + FooProvider<__Context__, T>, + {} + ") + } } -#[cgp_component(BarProvider)] -pub trait Bar { - fn bar(&self, value: &T); +snapshot_cgp_component! { + #[cgp_component(BarProvider)] + pub trait Bar { + fn bar(&self, value: &T); + } + + expand_open_bar(output) { + insta::assert_snapshot!(output, @" + pub trait Bar { + fn bar(&self, value: &T); + } + impl<__Context__, T> Bar for __Context__ + where + __Context__: BarProvider<__Context__, T>, + { + fn bar(&self, value: &T) { + __Context__::bar(self, value) + } + } + pub trait BarProvider< + __Context__, + T, + >: IsProviderFor { + fn bar(__context__: &__Context__, value: &T); + } + impl<__Provider__, __Context__, T> BarProvider<__Context__, T> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate: BarProvider<__Context__, T>, + { + fn bar(__context__: &__Context__, value: &T) { + <__Provider__ as DelegateComponent< + BarProviderComponent, + >>::Delegate::bar(__context__, value) + } + } + pub struct BarProviderComponent; + impl<__Context__, T> BarProvider<__Context__, T> for UseContext + where + __Context__: Bar, + { + fn bar(__context__: &__Context__, value: &T) { + __Context__::bar(__context__, value) + } + } + impl<__Context__, T> IsProviderFor for UseContext + where + __Context__: Bar, + {} + impl<__Context__, T, __Components__, __Path__> BarProvider<__Context__, T> + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: BarProvider<__Context__, T>, + { + fn bar(__context__: &__Context__, value: &T) { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::bar(__context__, value) + } + } + impl< + __Context__, + T, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor + + BarProvider<__Context__, T>, + {} + ") + } } -#[cgp_impl(new DummyFoo)] -impl FooProvider { - fn foo(&self, _value: &T) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyFoo)] + impl FooProvider { + fn foo(&self, _value: &T) {} + } + + expand_open_dummy_foo(output) { + insta::assert_snapshot!(output, @" + impl<__Context__, T> FooProvider<__Context__, T> for DummyFoo { + fn foo(__context__: &__Context__, _value: &T) {} + } + impl<__Context__, T> IsProviderFor for DummyFoo {} + pub struct DummyFoo; + ") + } } -#[cgp_impl(new DummyBar)] -impl BarProvider { - fn bar(&self, _value: &T) {} +snapshot_cgp_impl! { + #[cgp_impl(new DummyBar)] + impl BarProvider { + fn bar(&self, _value: &T) {} + } + + expand_open_dummy_bar(output) { + insta::assert_snapshot!(output, @" + impl<__Context__, T> BarProvider<__Context__, T> for DummyBar { + fn bar(__context__: &__Context__, _value: &T) {} + } + impl<__Context__, T> IsProviderFor for DummyBar {} + pub struct DummyBar; + ") + } } -delegate_components! { - App { - open {FooProviderComponent, BarProviderComponent}; +snapshot_delegate_components! { + delegate_components! { + App { + open {FooProviderComponent, BarProviderComponent}; - // FooProviderComponent => - // @FooProviderComponent, - // BarProviderComponent => - // @BarProviderComponent, + // FooProviderComponent => + // @FooProviderComponent, + // BarProviderComponent => + // @BarProviderComponent, - @FooProviderComponent.String: - DummyFoo, - @BarProviderComponent.{u32, u64, bool, usize, isize}: - DummyBar, + @FooProviderComponent.String: + DummyFoo, + @BarProviderComponent.{u32, u64, bool, usize, isize}: + DummyBar, + } + } + + expand_open_app(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for App { + type Delegate = RedirectLookup>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + RedirectLookup< + App, + PathCons, + >: IsProviderFor, + {} + impl DelegateComponent for App { + type Delegate = RedirectLookup>; + } + impl< + __Context__, + __Params__, + > IsProviderFor for App + where + RedirectLookup< + App, + PathCons, + >: IsProviderFor, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyFoo; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyFoo: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + impl< + __Wildcard__, + > DelegateComponent>> + for App { + type Delegate = DummyBar; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons>, + __Context__, + __Params__, + > for App + where + DummyBar: IsProviderFor< + PathCons>, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent: - String, - BarProviderComponent: [ - u32, - u64, - bool, - usize, - isize, - ], +snapshot_check_components! { + check_components! { + App { + FooProviderComponent: + String, + BarProviderComponent: [ + u32, + u64, + bool, + usize, + isize, + ], + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + impl __CheckApp for App {} + impl __CheckApp for App {} + impl __CheckApp for App {} + impl __CheckApp for App {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/namespace_tests/redirect.rs b/crates/tests/cgp-tests/tests/namespace_tests/redirect.rs index 4db7ee43..527e4cf2 100644 --- a/crates/tests/cgp-tests/tests/namespace_tests/redirect.rs +++ b/crates/tests/cgp-tests/tests/namespace_tests/redirect.rs @@ -1,36 +1,202 @@ use cgp::prelude::*; +use cgp_macro_test_util::{ + snapshot_cgp_component, snapshot_cgp_impl, snapshot_check_components, + snapshot_delegate_components, +}; -#[cgp_component(FooProvider)] -#[prefix(@bar.baz in DefaultNamespace)] -pub trait CanDoFoo { - fn foo(); +snapshot_cgp_component! { + #[cgp_component(FooProvider)] + #[prefix(@bar.baz in DefaultNamespace)] + pub trait CanDoFoo { + fn foo(); + } + + expand_redirect_foo(output) { + insta::assert_snapshot!(output, @" + pub trait CanDoFoo { + fn foo(); + } + impl<__Context__> CanDoFoo for __Context__ + where + __Context__: FooProvider<__Context__>, + { + fn foo() { + __Context__::foo() + } + } + pub trait FooProvider< + __Context__, + >: IsProviderFor { + fn foo(); + } + impl<__Provider__, __Context__> FooProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooProviderComponent, + >>::Delegate: FooProvider<__Context__>, + { + fn foo() { + <__Provider__ as DelegateComponent>::Delegate::foo() + } + } + pub struct FooProviderComponent; + impl<__Context__> FooProvider<__Context__> for UseContext + where + __Context__: CanDoFoo, + { + fn foo() { + __Context__::foo() + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: CanDoFoo, + {} + impl<__Context__, __Components__, __Path__> FooProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooProvider<__Context__>, + { + fn foo() { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo() + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooProvider<__Context__>, + {} + impl<__Components__> DefaultNamespace<__Components__> for FooProviderComponent { + type Delegate = RedirectLookup< + __Components__, + PathCons< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + PathCons< + Symbol<3, Chars<'b', Chars<'a', Chars<'z', Nil>>>>, + PathCons, + >, + >, + >; + } + ") + } } pub struct BarComponent; pub struct BazComponent; -#[cgp_impl(new TestProvider)] -impl FooProvider { - fn foo() {} +snapshot_cgp_impl! { + #[cgp_impl(new TestProvider)] + impl FooProvider { + fn foo() {} + } + + expand_redirect_test_provider(output) { + insta::assert_snapshot!(output, @" + impl<__Context__> FooProvider<__Context__> for TestProvider { + fn foo() {} + } + impl<__Context__> IsProviderFor for TestProvider {} + pub struct TestProvider; + ") + } } pub struct App; -delegate_components! { - App { - namespace DefaultNamespace; +snapshot_delegate_components! { + delegate_components! { + App { + namespace DefaultNamespace; + + // @bar: TestProvider, - // @bar: TestProvider, + @bar.baz: TestProvider, - @bar.baz: TestProvider, + // @bar.baz.FooProviderComponent: TestProvider, + } + } - // @bar.baz.FooProviderComponent: TestProvider, + expand_redirect_app(output) { + insta::assert_snapshot!(output, @" + impl<__Key__, __Value__> DelegateComponent<__Key__> for App + where + __Key__: DefaultNamespace, + { + type Delegate = __Value__; + } + impl< + __Key__, + __Value__, + __Context__, + __Params__, + > IsProviderFor<__Key__, __Context__, __Params__> for App + where + __Key__: DefaultNamespace, + __Value__: IsProviderFor<__Key__, __Context__, __Params__>, + {} + impl< + __Wildcard__, + > DelegateComponent< + PathCons< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + PathCons>>>, __Wildcard__>, + >, + > for App { + type Delegate = TestProvider; + } + impl< + __Wildcard__, + __Context__, + __Params__, + > IsProviderFor< + PathCons< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + PathCons>>>, __Wildcard__>, + >, + __Context__, + __Params__, + > for App + where + TestProvider: IsProviderFor< + PathCons< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + PathCons>>>, __Wildcard__>, + >, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - App { - FooProviderComponent, +snapshot_check_components! { + check_components! { + App { + FooProviderComponent, + } + } + + expand_check_app(output) { + insta::assert_snapshot!(output, @" + trait __CheckApp< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckApp for App {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/basic/components.rs b/crates/tests/cgp-tests/tests/preset_tests/basic/components.rs index 5514ee49..8b603884 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/basic/components.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/basic/components.rs @@ -1,21 +1,492 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_cgp_type}; -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_getter] -pub trait HasFoo: HasFooType { - fn foo(&self) -> &Self::Foo; +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasFoo: HasFooType { + fn foo(&self) -> &Self::Foo; + } + + expand_has_foo(output) { + insta::assert_snapshot!(output, @" + pub trait HasFoo: HasFooType { + fn foo(&self) -> &Self::Foo; + } + impl<__Context__> HasFoo for __Context__ + where + __Context__: HasFooType, + __Context__: FooGetter<__Context__>, + { + fn foo(&self) -> &Self::Foo { + __Context__::foo(self) + } + } + pub trait FooGetter<__Context__>: IsProviderFor + where + __Context__: HasFooType, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo; + } + impl<__Provider__, __Context__> FooGetter<__Context__> for __Provider__ + where + __Context__: HasFooType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__) + } + } + pub struct FooGetterComponent; + impl<__Context__> FooGetter<__Context__> for UseContext + where + __Context__: HasFooType, + __Context__: HasFoo, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + __Context__::foo(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + __Context__: HasFoo, + {} + impl<__Context__, __Components__, __Path__> FooGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: FooGetter<__Context__>, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + <__Components__ as DelegateComponent<__Path__>>::Delegate::foo(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooGetter<__Context__>, + {} + impl<__Context__> FooGetter<__Context__> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + {} + impl<__Context__, __Tag__> FooGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, __Provider__> FooGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter<__Context__, FooGetterComponent, Value = __Context__::Foo>, + {} + ") + } } -#[cgp_getter] -pub trait HasBar: HasBarType { - fn bar(&self) -> &Self::Bar; +snapshot_cgp_getter! { + #[cgp_getter] + pub trait HasBar: HasBarType { + fn bar(&self) -> &Self::Bar; + } + + expand_has_bar(output) { + insta::assert_snapshot!(output, @" + pub trait HasBar: HasBarType { + fn bar(&self) -> &Self::Bar; + } + impl<__Context__> HasBar for __Context__ + where + __Context__: HasBarType, + __Context__: BarGetter<__Context__>, + { + fn bar(&self) -> &Self::Bar { + __Context__::bar(self) + } + } + pub trait BarGetter<__Context__>: IsProviderFor + where + __Context__: HasBarType, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar; + } + impl<__Provider__, __Context__> BarGetter<__Context__> for __Provider__ + where + __Context__: HasBarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate: BarGetter<__Context__>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarGetterComponent; + impl<__Context__> BarGetter<__Context__> for UseContext + where + __Context__: HasBarType, + __Context__: HasBar, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + __Context__: HasBar, + {} + impl<__Context__, __Components__, __Path__> BarGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarGetter<__Context__>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarGetter<__Context__>, + {} + impl<__Context__> BarGetter<__Context__> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + {} + impl<__Context__, __Tag__> BarGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, __Provider__> BarGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter<__Context__, BarGetterComponent, Value = __Context__::Bar>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter<__Context__, BarGetterComponent, Value = __Context__::Bar>, + {} + ") + } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/basic/consumer_delegate.rs b/crates/tests/cgp-tests/tests/preset_tests/basic/consumer_delegate.rs index 12130a7f..b65926c9 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/basic/consumer_delegate.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/basic/consumer_delegate.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::basic::components::{ BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, HasBar, @@ -18,11 +19,25 @@ impl HasBar for MyContext { } } -check_components! { - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - FooGetterComponent, +snapshot_check_components! { + check_components! { + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + FooGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/basic/contexts.rs b/crates/tests/cgp-tests/tests/preset_tests/basic/contexts.rs index e9a03f01..bd379bbf 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/basic/contexts.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/basic/contexts.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_components}; use crate::preset_tests::basic::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -12,18 +13,48 @@ pub struct MyContext { pub bar: (), } -delegate_components! { - MyContext { - BarGetterComponent: UseField, +snapshot_delegate_components! { + delegate_components! { + MyContext { + BarGetterComponent: UseField, + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @r#" + impl DelegateComponent for MyContext { + type Delegate = UseField; + } + impl<__Context__, __Params__> IsProviderFor + for MyContext + where + UseField: IsProviderFor, + {} + "#) } } -check_components! { - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - FooGetterComponent, - BarGetterComponent, +snapshot_check_components! { + check_components! { + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + FooGetterComponent, + BarGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/generics/components.rs b/crates/tests/cgp-tests/tests/preset_tests/generics/components.rs index 3c314ad5..4ff6ecf2 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/generics/components.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/generics/components.rs @@ -1,28 +1,523 @@ use core::marker::PhantomData; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_cgp_type}; -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_getter { - name: FooGetterComponent, - provider: FooGetter, -}] -pub trait HasFooAt: HasFooType { - fn foo(&self, _tag: PhantomData) -> &Self::Foo; +snapshot_cgp_getter! { + #[cgp_getter { + name: FooGetterComponent, + provider: FooGetter, + }] + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + + expand_has_foo_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + impl<__Context__, I> HasFooAt for __Context__ + where + __Context__: HasFooType, + __Context__: FooGetter<__Context__, I>, + { + fn foo(&self, _tag: PhantomData) -> &Self::Foo { + __Context__::foo(self, _tag) + } + } + pub trait FooGetter< + __Context__, + I, + >: IsProviderFor, __Context__, (I)> + where + __Context__: HasFooType, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo; + } + impl<__Provider__, __Context__, I> FooGetter<__Context__, I> for __Provider__ + where + __Context__: HasFooType, + __Provider__: DelegateComponent> + + IsProviderFor, __Context__, (I)>, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct FooGetterComponent(pub ::core::marker::PhantomData<(I)>); + impl<__Context__, I> FooGetter<__Context__, I> for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + __Context__::foo(__context__, _tag) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> + for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + {} + impl<__Context__, I, __Components__, __Path__> FooGetter<__Context__, I> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: FooGetter<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I, + __Components__, + __Path__, + > IsProviderFor, __Context__, (I)> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor, __Context__, (I)> + + FooGetter<__Context__, I>, + {} + impl<__Context__, I> FooGetter<__Context__, I> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + {} + impl<__Context__, I, __Tag__> FooGetter<__Context__, I> for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, __Tag__> IsProviderFor, __Context__, (I)> + for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, I, __Provider__> FooGetter<__Context__, I> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::>, + ) + } + } + impl<__Context__, I, __Provider__> IsProviderFor, __Context__, (I)> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value = __Context__::Foo, + >, + {} + ") + } } -#[cgp_getter { - provider: BarGetter, -}] -pub trait HasBar: HasBarType { - fn bar(&self) -> &Self::Bar; +snapshot_cgp_getter! { + #[cgp_getter { + provider: BarGetter, + }] + pub trait HasBar: HasBarType { + fn bar(&self) -> &Self::Bar; + } + + expand_has_bar(output) { + insta::assert_snapshot!(output, @" + pub trait HasBar: HasBarType { + fn bar(&self) -> &Self::Bar; + } + impl<__Context__> HasBar for __Context__ + where + __Context__: HasBarType, + __Context__: BarGetter<__Context__>, + { + fn bar(&self) -> &Self::Bar { + __Context__::bar(self) + } + } + pub trait BarGetter<__Context__>: IsProviderFor + where + __Context__: HasBarType, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar; + } + impl<__Provider__, __Context__> BarGetter<__Context__> for __Provider__ + where + __Context__: HasBarType, + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate: BarGetter<__Context__>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarGetterComponent; + impl<__Context__> BarGetter<__Context__> for UseContext + where + __Context__: HasBarType, + __Context__: HasBar, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Context__::bar(__context__) + } + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + __Context__: HasBar, + {} + impl<__Context__, __Components__, __Path__> BarGetter<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent<__Path__>>::Delegate: BarGetter<__Context__>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Components__ as DelegateComponent<__Path__>>::Delegate::bar(__context__) + } + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarGetter<__Context__>, + {} + impl<__Context__> BarGetter<__Context__> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ) + } + } + impl<__Context__> IsProviderFor for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + {} + impl<__Context__, __Tag__> BarGetter<__Context__> for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, __Tag__> IsProviderFor + for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, __Provider__> BarGetter<__Context__> for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter<__Context__, BarGetterComponent, Value = __Context__::Bar>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::, + ) + } + } + impl<__Context__, __Provider__> IsProviderFor + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter<__Context__, BarGetterComponent, Value = __Context__::Bar>, + {} + ") + } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs b/crates/tests/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs index 55bd3295..4515d852 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/generics/consumer_delegate.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::generics::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -12,18 +13,45 @@ pub struct MyContext { pub bar: T, } -check_components! { - #[check_trait(CanUseMyContext)] - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - BarGetterComponent, +snapshot_check_components! { + check_components! { + #[check_trait(CanUseMyContext)] + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + BarGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseMyContext for MyContext {} + impl CanUseMyContext for MyContext {} + impl CanUseMyContext for MyContext {} + ") } } -check_components! { - #[check_trait(CanUseFooGetter)] - MyContext { - FooGetterComponent>: Index, +snapshot_check_components! { + check_components! { + #[check_trait(CanUseFooGetter)] + MyContext { + FooGetterComponent>: Index, + } + } + + expand_check_my_context_2(output) { + insta::assert_snapshot!(output, @" + trait CanUseFooGetter< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseFooGetter>, Index> + for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/generics/contexts.rs b/crates/tests/cgp-tests/tests/preset_tests/generics/contexts.rs index 55bd3295..4515d852 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/generics/contexts.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/generics/contexts.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::generics::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -12,18 +13,45 @@ pub struct MyContext { pub bar: T, } -check_components! { - #[check_trait(CanUseMyContext)] - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - BarGetterComponent, +snapshot_check_components! { + check_components! { + #[check_trait(CanUseMyContext)] + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + BarGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait CanUseMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseMyContext for MyContext {} + impl CanUseMyContext for MyContext {} + impl CanUseMyContext for MyContext {} + ") } } -check_components! { - #[check_trait(CanUseFooGetter)] - MyContext { - FooGetterComponent>: Index, +snapshot_check_components! { + check_components! { + #[check_trait(CanUseFooGetter)] + MyContext { + FooGetterComponent>: Index, + } + } + + expand_check_my_context_2(output) { + insta::assert_snapshot!(output, @" + trait CanUseFooGetter< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseFooGetter>, Index> + for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/components.rs b/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/components.rs index 7cd32187..c76a716d 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/components.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/components.rs @@ -1,29 +1,548 @@ use core::marker::PhantomData; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_cgp_getter, snapshot_cgp_type}; -#[cgp_type] -pub trait HasFooType { - type Foo; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasFooType { + type Foo; + } + + expand_has_foo_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooType { + type Foo; + } + impl<__Context__> HasFooType for __Context__ + where + __Context__: FooTypeProvider<__Context__>, + { + type Foo = <__Context__ as FooTypeProvider<__Context__>>::Foo; + } + pub trait FooTypeProvider< + __Context__, + >: IsProviderFor { + type Foo; + } + impl<__Provider__, __Context__> FooTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Provider__ as DelegateComponent< + FooTypeProviderComponent, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + pub struct FooTypeProviderComponent; + impl<__Context__> FooTypeProvider<__Context__> for UseContext + where + __Context__: HasFooType, + { + type Foo = <__Context__ as HasFooType>::Foo; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasFooType, + {} + impl<__Context__, __Components__, __Path__> FooTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: FooTypeProvider<__Context__>, + { + type Foo = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as FooTypeProvider<__Context__>>::Foo; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + FooTypeProvider<__Context__>, + {} + impl FooTypeProvider<__Context__> for UseType + where + Foo:, + { + type Foo = Foo; + } + impl IsProviderFor + for UseType + where + Foo:, + {} + impl<__Provider__, Foo, __Context__> FooTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + { + type Foo = Foo; + } + impl< + __Provider__, + Foo, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, FooTypeProviderComponent, Type = Foo>, + Foo:, + {} + ") + } } -#[cgp_type] -pub trait HasBarType { - type Bar; +snapshot_cgp_type! { + #[cgp_type] + pub trait HasBarType { + type Bar; + } + + expand_has_bar_type(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarType { + type Bar; + } + impl<__Context__> HasBarType for __Context__ + where + __Context__: BarTypeProvider<__Context__>, + { + type Bar = <__Context__ as BarTypeProvider<__Context__>>::Bar; + } + pub trait BarTypeProvider< + __Context__, + >: IsProviderFor { + type Bar; + } + impl<__Provider__, __Context__> BarTypeProvider<__Context__> for __Provider__ + where + __Provider__: DelegateComponent + + IsProviderFor, + <__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Provider__ as DelegateComponent< + BarTypeProviderComponent, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + pub struct BarTypeProviderComponent; + impl<__Context__> BarTypeProvider<__Context__> for UseContext + where + __Context__: HasBarType, + { + type Bar = <__Context__ as HasBarType>::Bar; + } + impl<__Context__> IsProviderFor for UseContext + where + __Context__: HasBarType, + {} + impl<__Context__, __Components__, __Path__> BarTypeProvider<__Context__> + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: BarTypeProvider<__Context__>, + { + type Bar = <<__Components__ as DelegateComponent< + __Path__, + >>::Delegate as BarTypeProvider<__Context__>>::Bar; + } + impl< + __Context__, + __Components__, + __Path__, + > IsProviderFor + for RedirectLookup<__Components__, __Path__> + where + __Components__: DelegateComponent<__Path__>, + <__Components__ as DelegateComponent< + __Path__, + >>::Delegate: IsProviderFor + + BarTypeProvider<__Context__>, + {} + impl BarTypeProvider<__Context__> for UseType + where + Bar:, + { + type Bar = Bar; + } + impl IsProviderFor + for UseType + where + Bar:, + {} + impl<__Provider__, Bar, __Context__> BarTypeProvider<__Context__> + for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + { + type Bar = Bar; + } + impl< + __Provider__, + Bar, + __Context__, + > IsProviderFor for WithProvider<__Provider__> + where + __Provider__: TypeProvider<__Context__, BarTypeProviderComponent, Type = Bar>, + Bar:, + {} + ") + } } -#[cgp_getter { - name: FooGetterComponent, - provider: FooGetter, -}] -pub trait HasFooAt: HasFooType { - fn foo(&self, _tag: PhantomData) -> &Self::Foo; +snapshot_cgp_getter! { + #[cgp_getter { + name: FooGetterComponent, + provider: FooGetter, + }] + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + + expand_has_foo_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasFooAt: HasFooType { + fn foo(&self, _tag: PhantomData) -> &Self::Foo; + } + impl<__Context__, I> HasFooAt for __Context__ + where + __Context__: HasFooType, + __Context__: FooGetter<__Context__, I>, + { + fn foo(&self, _tag: PhantomData) -> &Self::Foo { + __Context__::foo(self, _tag) + } + } + pub trait FooGetter< + __Context__, + I, + >: IsProviderFor, __Context__, (I)> + where + __Context__: HasFooType, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo; + } + impl<__Provider__, __Context__, I> FooGetter<__Context__, I> for __Provider__ + where + __Context__: HasFooType, + __Provider__: DelegateComponent> + + IsProviderFor, __Context__, (I)>, + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate: FooGetter<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Provider__ as DelegateComponent< + FooGetterComponent, + >>::Delegate::foo(__context__, _tag) + } + } + pub struct FooGetterComponent(pub ::core::marker::PhantomData<(I)>); + impl<__Context__, I> FooGetter<__Context__, I> for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + __Context__::foo(__context__, _tag) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> + for UseContext + where + __Context__: HasFooType, + __Context__: HasFooAt, + {} + impl<__Context__, I, __Components__, __Path__> FooGetter<__Context__, I> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: FooGetter<__Context__, I>, + { + fn foo(__context__: &__Context__, _tag: PhantomData) -> &__Context__::Foo { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::foo(__context__, _tag) + } + } + impl< + __Context__, + I, + __Components__, + __Path__, + > IsProviderFor, __Context__, (I)> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasFooType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor, __Context__, (I)> + + FooGetter<__Context__, I>, + {} + impl<__Context__, I> FooGetter<__Context__, I> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + >, + ) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> for UseFields + where + __Context__: HasFooType, + __Context__: HasField< + Symbol<3, Chars<'f', Chars<'o', Chars<'o', Nil>>>>, + Value = __Context__::Foo, + >, + {} + impl<__Context__, I, __Tag__> FooGetter<__Context__, I> for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, __Tag__> IsProviderFor, __Context__, (I)> + for UseField<__Tag__> + where + __Context__: HasFooType, + __Context__: HasField<__Tag__, Value = __Context__::Foo>, + {} + impl<__Context__, I, __Provider__> FooGetter<__Context__, I> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value = __Context__::Foo, + >, + { + fn foo(__context__: &__Context__, _phantom: PhantomData) -> &__Context__::Foo { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::>, + ) + } + } + impl<__Context__, I, __Provider__> IsProviderFor, __Context__, (I)> + for WithProvider<__Provider__> + where + __Context__: HasFooType, + __Provider__: FieldGetter< + __Context__, + FooGetterComponent, + Value = __Context__::Foo, + >, + {} + ") + } } -#[cgp_getter { - name: BarGetterComponent, - provider: BarGetter, -}] -pub trait HasBarAt: HasBarType { - fn bar(&self) -> &Self::Bar; +snapshot_cgp_getter! { + #[cgp_getter { + name: BarGetterComponent, + provider: BarGetter, + }] + pub trait HasBarAt: HasBarType { + fn bar(&self) -> &Self::Bar; + } + + expand_has_bar_at(output) { + insta::assert_snapshot!(output, @" + pub trait HasBarAt: HasBarType { + fn bar(&self) -> &Self::Bar; + } + impl<__Context__, I> HasBarAt for __Context__ + where + __Context__: HasBarType, + __Context__: BarGetter<__Context__, I>, + { + fn bar(&self) -> &Self::Bar { + __Context__::bar(self) + } + } + pub trait BarGetter< + __Context__, + I, + >: IsProviderFor, __Context__, (I)> + where + __Context__: HasBarType, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar; + } + impl<__Provider__, __Context__, I> BarGetter<__Context__, I> for __Provider__ + where + __Context__: HasBarType, + __Provider__: DelegateComponent> + + IsProviderFor, __Context__, (I)>, + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate: BarGetter<__Context__, I>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Provider__ as DelegateComponent< + BarGetterComponent, + >>::Delegate::bar(__context__) + } + } + pub struct BarGetterComponent(pub ::core::marker::PhantomData<(I)>); + impl<__Context__, I> BarGetter<__Context__, I> for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Context__::bar(__context__) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> + for UseContext + where + __Context__: HasBarType, + __Context__: HasBarAt, + {} + impl<__Context__, I, __Components__, __Path__> BarGetter<__Context__, I> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: BarGetter<__Context__, I>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate::bar(__context__) + } + } + impl< + __Context__, + I, + __Components__, + __Path__, + > IsProviderFor, __Context__, (I)> + for RedirectLookup<__Components__, __Path__> + where + __Context__: HasBarType, + __Path__: ConcatPath>, + __Components__: DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >, + <__Components__ as DelegateComponent< + <__Path__ as ConcatPath>>::Output, + >>::Delegate: IsProviderFor, __Context__, (I)> + + BarGetter<__Context__, I>, + {} + impl<__Context__, I> BarGetter<__Context__, I> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__ + .get_field( + ::core::marker::PhantomData::< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + >, + ) + } + } + impl<__Context__, I> IsProviderFor, __Context__, (I)> for UseFields + where + __Context__: HasBarType, + __Context__: HasField< + Symbol<3, Chars<'b', Chars<'a', Chars<'r', Nil>>>>, + Value = __Context__::Bar, + >, + {} + impl<__Context__, I, __Tag__> BarGetter<__Context__, I> for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __context__.get_field(::core::marker::PhantomData::<__Tag__>) + } + } + impl<__Context__, I, __Tag__> IsProviderFor, __Context__, (I)> + for UseField<__Tag__> + where + __Context__: HasBarType, + __Context__: HasField<__Tag__, Value = __Context__::Bar>, + {} + impl<__Context__, I, __Provider__> BarGetter<__Context__, I> + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterComponent, + Value = __Context__::Bar, + >, + { + fn bar(__context__: &__Context__) -> &__Context__::Bar { + __Provider__::get_field( + __context__, + ::core::marker::PhantomData::>, + ) + } + } + impl<__Context__, I, __Provider__> IsProviderFor, __Context__, (I)> + for WithProvider<__Provider__> + where + __Context__: HasBarType, + __Provider__: FieldGetter< + __Context__, + BarGetterComponent, + Value = __Context__::Bar, + >, + {} + ") + } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/contexts.rs b/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/contexts.rs index 84248ef6..ef2052bc 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/contexts.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/generics_inheritance/contexts.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::generics_inheritance::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -12,19 +13,45 @@ pub struct MyContext { pub bar: (), } -check_components! { - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, +snapshot_check_components! { + check_components! { + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } } -check_components! { - #[check_trait(CanUseFooGetter)] - MyContext { - [ - FooGetterComponent, - BarGetterComponent, - ]: I, +snapshot_check_components! { + check_components! { + #[check_trait(CanUseFooGetter)] + MyContext { + [ + FooGetterComponent, + BarGetterComponent, + ]: I, + } + } + + expand_check_my_context_2(output) { + insta::assert_snapshot!(output, @" + trait CanUseFooGetter< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl CanUseFooGetter, I> for MyContext {} + impl CanUseFooGetter, I> for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/inheritance/contexts.rs b/crates/tests/cgp-tests/tests/preset_tests/inheritance/contexts.rs index cda5816c..86b4b6f7 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/inheritance/contexts.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/inheritance/contexts.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::basic::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -12,12 +13,27 @@ pub struct MyContext { pub bar: (), } -check_components! { - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - FooGetterComponent, - BarGetterComponent, +snapshot_check_components! { + check_components! { + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + FooGetterComponent, + BarGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/nested_inheritance/contexts.rs b/crates/tests/cgp-tests/tests/preset_tests/nested_inheritance/contexts.rs index da718ab4..da5aaa69 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/nested_inheritance/contexts.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/nested_inheritance/contexts.rs @@ -1,4 +1,5 @@ use cgp::prelude::*; +use cgp_macro_test_util::snapshot_check_components; use crate::preset_tests::basic::components::{ BarGetterComponent, BarTypeProviderComponent, FooGetterComponent, FooTypeProviderComponent, @@ -14,12 +15,27 @@ pub struct MyContext { pub bar: (), } -check_components! { - MyContext { - FooTypeProviderComponent, - BarTypeProviderComponent, - FooGetterComponent, - BarGetterComponent, +snapshot_check_components! { + check_components! { + MyContext { + FooTypeProviderComponent, + BarTypeProviderComponent, + FooGetterComponent, + BarGetterComponent, + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } } diff --git a/crates/tests/cgp-tests/tests/preset_tests/wrapped/context.rs b/crates/tests/cgp-tests/tests/preset_tests/wrapped/context.rs index c6ea5526..5a1ab8a3 100644 --- a/crates/tests/cgp-tests/tests/preset_tests/wrapped/context.rs +++ b/crates/tests/cgp-tests/tests/preset_tests/wrapped/context.rs @@ -2,26 +2,74 @@ use core::convert::Infallible; use cgp::core::error::{ErrorRaiserComponent, ErrorTypeProviderComponent}; use cgp::prelude::*; +use cgp_macro_test_util::{snapshot_check_components, snapshot_delegate_components}; use crate::preset_tests::wrapped::preset::{BoxError, ErrorHandlerPreset}; pub struct MyContext; -delegate_components! { - MyContext { - ErrorTypeProviderComponent: - UseType, - ErrorRaiserComponent: - ErrorHandlerPreset::Provider, +snapshot_delegate_components! { + delegate_components! { + MyContext { + ErrorTypeProviderComponent: + UseType, + ErrorRaiserComponent: + ErrorHandlerPreset::Provider, + } + } + + expand_my_context(output) { + insta::assert_snapshot!(output, @" + impl DelegateComponent for MyContext { + type Delegate = UseType; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + UseType< + BoxError, + >: IsProviderFor, + {} + impl DelegateComponent for MyContext { + type Delegate = ErrorHandlerPreset::Provider; + } + impl< + __Context__, + __Params__, + > IsProviderFor for MyContext + where + ErrorHandlerPreset::Provider: IsProviderFor< + ErrorRaiserComponent, + __Context__, + __Params__, + >, + {} + ") } } -check_components! { - MyContext { - ErrorRaiserComponent: [ - BoxError, - Infallible, - std::io::Error, - ] +snapshot_check_components! { + check_components! { + MyContext { + ErrorRaiserComponent: [ + BoxError, + Infallible, + std::io::Error, + ] + } + } + + expand_check_my_context(output) { + insta::assert_snapshot!(output, @" + trait __CheckMyContext< + __Component__, + __Params__: ?Sized, + >: CanUseComponent<__Component__, __Params__> {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + impl __CheckMyContext for MyContext {} + ") } }