Add Transformer impls to handle handle Option<T> properties (#878)

* Add Transformer impls to handle handle Option<T> properties

* Add test

* More tests
This commit is contained in:
AlephAlpha 2020-01-19 21:39:08 +08:00 committed by Justin Starry
parent ffadafe0c2
commit 3195b50d12
3 changed files with 125 additions and 43 deletions

View File

@ -249,6 +249,33 @@ impl<'a> Transformer<&'a str, String> for VComp {
}
}
impl<T> Transformer<T, Option<T>> for VComp {
fn transform(from: T) -> Option<T> {
Some(from)
}
}
impl<'a, T> Transformer<&'a T, Option<T>> for VComp
where
T: Clone,
{
fn transform(from: &T) -> Option<T> {
Some(from.clone())
}
}
impl<'a> Transformer<&'a str, Option<String>> for VComp {
fn transform(from: &'a str) -> Option<String> {
Some(from.to_owned())
}
}
impl<'a> Transformer<Option<&'a str>, Option<String>> for VComp {
fn transform(from: Option<&'a str>) -> Option<String> {
from.map(|s| s.to_owned())
}
}
impl PartialEq for VComp {
fn eq(&self, other: &VComp) -> bool {
self.type_id == other.type_id

View File

@ -127,38 +127,47 @@ error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder<C
64 | html! { <Child unknown="unknown" /> };
| ^^^^^^^ method not found in `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>`
error[E0308]: mismatched types
error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer<(), std::string::String>` is not satisfied
--> $DIR/html-component-fail.rs:66:33
|
66 | html! { <Child int=1 string={} /> };
| ^^ expected struct `std::string::String`, found ()
| ^^ the trait `yew::virtual_dom::Transformer<(), std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp`
|
= note: expected type `std::string::String`
found type `()`
= help: the following implementations were found:
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, T>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, std::option::Option<T>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::option::Option<std::string::String>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::string::String>>
and 3 others
= note: required by `yew::virtual_dom::Transformer::transform`
error[E0308]: mismatched types
error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer<{integer}, std::string::String>` is not satisfied
--> $DIR/html-component-fail.rs:67:33
|
67 | html! { <Child int=1 string=3 /> };
| ^
| |
| expected struct `std::string::String`, found integer
| help: try using a conversion method: `3.to_string()`
| ^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp`
|
= note: expected type `std::string::String`
found type `{integer}`
= help: the following implementations were found:
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, T>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, std::option::Option<T>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::option::Option<std::string::String>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::string::String>>
and 3 others
= note: required by `yew::virtual_dom::Transformer::transform`
error[E0308]: mismatched types
error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer<{integer}, std::string::String>` is not satisfied
--> $DIR/html-component-fail.rs:68:33
|
68 | html! { <Child int=1 string={3} /> };
| ^^^
| |
| expected struct `std::string::String`, found integer
| help: try using a conversion method: `{3}.to_string()`
| ^^^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp`
|
= note: expected type `std::string::String`
found type `{integer}`
= help: the following implementations were found:
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, T>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, std::option::Option<T>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::option::Option<std::string::String>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::string::String>>
and 3 others
= note: required by `yew::virtual_dom::Transformer::transform`
error[E0308]: mismatched types
--> $DIR/html-component-fail.rs:69:30
@ -169,16 +178,19 @@ error[E0308]: mismatched types
= note: expected type `yew::html::NodeRef`
found type `()`
error[E0308]: mismatched types
error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer<u32, i32>` is not satisfied
--> $DIR/html-component-fail.rs:71:24
|
71 | html! { <Child int=0u32 /> };
| ^^^^ expected i32, found u32
| ^^^^ the trait `yew::virtual_dom::Transformer<u32, i32>` is not implemented for `yew::virtual_dom::vcomp::VComp`
|
help: you can convert an `u32` to `i32` and panic if the converted value wouldn't fit
|
71 | html! { <Child int=0u32.try_into().unwrap() /> };
| ^^^^^^^^^^^^^^^^^^^^^^^^
= help: the following implementations were found:
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, T>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a T, std::option::Option<T>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::option::Option<std::string::String>>>
<yew::virtual_dom::vcomp::VComp as yew::virtual_dom::Transformer<&'a str, std::string::String>>
and 3 others
= note: required by `yew::virtual_dom::Transformer::transform`
error[E0599]: no method named `string` found for type `ChildPropertiesBuilder<ChildPropertiesBuilderStep_missing_required_prop_int>` in the current scope
--> $DIR/html-component-fail.rs:72:20

View File

@ -1,8 +1,8 @@
#![recursion_limit = "256"]
use std::marker::PhantomData;
use yew::prelude::*;
use yew::html::ChildrenRenderer;
use yew::prelude::*;
use yew::virtual_dom::{VChild, VNode};
pub struct Generic<G> {
@ -13,18 +13,30 @@ impl Component for Generic<String> {
type Message = ();
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
impl Component for Generic<Vec<String>> {
type Message = ();
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
#[derive(Clone, Properties, Default)]
@ -39,9 +51,15 @@ impl Component for Container {
type Message = ();
type Properties = ContainerProperties;
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
#[derive(Clone)]
@ -76,6 +94,7 @@ pub struct ChildProperties {
pub string: String,
#[props(required)]
pub int: i32,
pub opt_str: Option<String>,
pub vec: Vec<i32>,
pub optional_callback: Option<Callback<()>>,
}
@ -85,9 +104,15 @@ impl Component for Child {
type Message = ();
type Properties = ChildProperties;
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
pub struct AltChild;
@ -95,9 +120,15 @@ impl Component for AltChild {
type Message = ();
type Properties = ();
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
#[derive(Clone, Properties, Default)]
@ -112,9 +143,15 @@ impl Component for ChildContainer {
type Message = ();
type Properties = ChildContainerProperties;
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self { unimplemented!() }
fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() }
fn view(&self) -> Html { unimplemented!() }
fn create(_: Self::Properties, _: ComponentLink<Self>) -> Self {
unimplemented!()
}
fn update(&mut self, _: Self::Message) -> ShouldRender {
unimplemented!()
}
fn view(&self) -> Html {
unimplemented!()
}
}
mod scoped {
@ -158,6 +195,11 @@ fn compile_pass() {
<Child int=1 vec={vec![1]} />
<Child string={String::from("child")} int=1 />
<Child opt_str="child" int=1 />
<Child opt_str=String::from("child") int=1 />
<Child opt_str=Some("child") int=1 />
<Child opt_str=Some(String::from("child")) int=1 />
// backwards compat
<Child: string="child", int=3, />
</>
@ -172,6 +214,7 @@ fn compile_pass() {
<>
<Child int=1 />
<Child int=1 optional_callback=Some(Callback::from(|_| ())) />
<Child int=1 optional_callback=Callback::from(|_| ()) />
<Child int=1 optional_callback=None />
</>
};