From a0b2e96b6b47d27587a1a452725043a3a9bc6300 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 22 Feb 2020 20:50:34 +0100 Subject: [PATCH 01/38] Initial --- crates/macro/src/html_tree/html_component.rs | 2 +- tests/macro/html-component-fail.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index a1afac7c122..f5b4070f8b3 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -451,7 +451,7 @@ impl Parse for WithProps { if ident.0 == "ref" { node_ref = Some(prop.value); } else { - return Err(syn::Error::new_spanned(&prop.label, "unexpected token")); + return Err(syn::Error::new_spanned(&prop.label, "Using special syntax [with props] along with named prop is not allowed")); } } diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index d3836290055..b67e79fc40f 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -59,6 +59,8 @@ fn compile_fail() { html! { }; html! { }; html! { }; + html! { }; + html! { }; html! { }; html! { }; html! { }; From ad352038f4f22c4d612d1710f64d22f4d6b85070 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 23 Feb 2020 15:22:08 +0100 Subject: [PATCH 02/38] formatting --- crates/macro/src/html_tree/html_component.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index f5b4070f8b3..31e01f7db47 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -451,7 +451,10 @@ impl Parse for WithProps { if ident.0 == "ref" { node_ref = Some(prop.value); } else { - return Err(syn::Error::new_spanned(&prop.label, "Using special syntax [with props] along with named prop is not allowed")); + return Err(syn::Error::new_spanned( + &prop.label, + "Using special syntax [with props] along with named prop is not allowed", + )); } } From d41d46609604d5abdf6b6d00f2470ed5cce8de06 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 23 Feb 2020 17:00:02 +0100 Subject: [PATCH 03/38] wip --- crates/macro/src/html_tree/html_component.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 31e01f7db47..cd0dc0d087f 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -392,8 +392,17 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); + while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); + let prop = input.parse::(); + let with = input.parse::()?; + if with == "with" { + return Err(input.error("expected to find `with` token")); + } + + if let Ok(value) = prop { + props.push(value); + } } let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); From 5ca168585d7c8bcaa69bd488a7cefed9ba9bb972 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 23 Feb 2020 17:17:38 +0100 Subject: [PATCH 04/38] add util fn --- crates/macro/src/html_tree/html_component.rs | 23 ++++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index cd0dc0d087f..70dfceff9c0 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -384,6 +384,14 @@ impl Parse for Props { } } +fn expect_with_props(input: ParseStream, allow: bool) -> bool { + match input.parse::() { + Ok(with) => (with == "with") == allow, + Err(_) => false + } + +} + struct ListProps { props: Vec, node_ref: Option, @@ -394,15 +402,13 @@ impl Parse for ListProps { let mut props: Vec = Vec::new(); while HtmlProp::peek(input.cursor()).is_some() { - let prop = input.parse::(); - let with = input.parse::()?; - if with == "with" { - return Err(input.error("expected to find `with` token")); - } + props.push(input.parse::()?); - if let Ok(value) = prop { - props.push(value); + if expect_with_props(input, true) { + return Err(input.error("Using special syntax [with props] along with named prop is not allowed")); } + + } let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); @@ -446,6 +452,9 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { + if expect_with_props(input, false) { + return Err(input.error("expected to find `with` token")); + } let with = input.parse::()?; if with != "with" { return Err(input.error("expected to find `with` token")); From 05388136d58b13238402e7b65cc6ecbe2c9b3a5c Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 23 Feb 2020 17:38:14 +0100 Subject: [PATCH 05/38] message update --- crates/macro/src/html_tree/html_component.rs | 21 +++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 70dfceff9c0..2fdd620ad2b 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -387,9 +387,8 @@ impl Parse for Props { fn expect_with_props(input: ParseStream, allow: bool) -> bool { match input.parse::() { Ok(with) => (with == "with") == allow, - Err(_) => false + Err(_) => false, } - } struct ListProps { @@ -402,13 +401,15 @@ impl Parse for ListProps { let mut props: Vec = Vec::new(); while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); - - if expect_with_props(input, true) { - return Err(input.error("Using special syntax [with props] along with named prop is not allowed")); + if let Ok(prop) = input.parse::() { + if expect_with_props(input, true) { + return Err(syn::Error::new_spanned( + &prop.label, + "Using special syntax [with props] along with named prop is not allowed", + )); + } + props.push(prop); } - - } let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); @@ -455,10 +456,6 @@ impl Parse for WithProps { if expect_with_props(input, false) { return Err(input.error("expected to find `with` token")); } - let with = input.parse::()?; - if with != "with" { - return Err(input.error("expected to find `with` token")); - } let props = input.parse::()?; let _ = input.parse::(); From 166e4b4a2a59ad5894cd50cff43538e5ab648571 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 23 Feb 2020 18:28:10 +0100 Subject: [PATCH 06/38] refactor --- crates/macro/src/html_tree/html_component.rs | 31 +++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 2fdd620ad2b..c9d9c277822 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -359,6 +359,16 @@ impl Props { Props::None => None, } } + fn expect_with_props(input: ParseStream) -> ParseResult { + let token = input.parse::()?; + Ok(token == "with") + } + fn collision_error(prop: &HtmlProp) -> syn::Error { + syn::Error::new_spanned( + &prop.label, + "Using special syntax [with props] along with named prop is not allowed", + ) + } } impl PeekValue for Props { @@ -384,13 +394,6 @@ impl Parse for Props { } } -fn expect_with_props(input: ParseStream, allow: bool) -> bool { - match input.parse::() { - Ok(with) => (with == "with") == allow, - Err(_) => false, - } -} - struct ListProps { props: Vec, node_ref: Option, @@ -402,11 +405,8 @@ impl Parse for ListProps { while HtmlProp::peek(input.cursor()).is_some() { if let Ok(prop) = input.parse::() { - if expect_with_props(input, true) { - return Err(syn::Error::new_spanned( - &prop.label, - "Using special syntax [with props] along with named prop is not allowed", - )); + if Props::expect_with_props(input).unwrap() { + return Err(Props::collision_error(&prop)); } props.push(prop); } @@ -453,7 +453,7 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { - if expect_with_props(input, false) { + if !Props::expect_with_props(input).unwrap() { return Err(input.error("expected to find `with` token")); } let props = input.parse::()?; @@ -466,10 +466,7 @@ impl Parse for WithProps { if ident.0 == "ref" { node_ref = Some(prop.value); } else { - return Err(syn::Error::new_spanned( - &prop.label, - "Using special syntax [with props] along with named prop is not allowed", - )); + return Err(Props::collision_error(&prop)); } } From 1516923655d971214f33322f084854d94d3f6064 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Feb 2020 20:27:50 +0100 Subject: [PATCH 07/38] update error logic --- crates/macro/src/html_tree/html_component.rs | 31 +++++++++----------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index c9d9c277822..9ee86d68223 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -359,16 +359,6 @@ impl Props { Props::None => None, } } - fn expect_with_props(input: ParseStream) -> ParseResult { - let token = input.parse::()?; - Ok(token == "with") - } - fn collision_error(prop: &HtmlProp) -> syn::Error { - syn::Error::new_spanned( - &prop.label, - "Using special syntax [with props] along with named prop is not allowed", - ) - } } impl PeekValue for Props { @@ -403,12 +393,15 @@ impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - if let Ok(prop) = input.parse::() { - if Props::expect_with_props(input).unwrap() { - return Err(Props::collision_error(&prop)); + loop { + match HtmlProp::peek(input.cursor()) { + Some(()) => props.push(input.parse::()?), + None => { + if input.cursor().token_stream().to_string().contains("with") { + return Err(input.error("Using special syntax [with props] along with named prop is not allowed")); + }; + break; } - props.push(prop); } } @@ -453,7 +446,8 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { - if !Props::expect_with_props(input).unwrap() { + let token = input.parse::()?; + if token != "with" { return Err(input.error("expected to find `with` token")); } let props = input.parse::()?; @@ -466,7 +460,10 @@ impl Parse for WithProps { if ident.0 == "ref" { node_ref = Some(prop.value); } else { - return Err(Props::collision_error(&prop)); + return Err(syn::Error::new_spanned( + &prop.label, + "Using special syntax [with props] along with named prop is not allowed", + )); } } From 1cefeae5e0f72d62c137a831a80cf1dd553f40ae Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Feb 2020 20:44:08 +0100 Subject: [PATCH 08/38] message refactor --- crates/macro/src/html_tree/html_component.rs | 21 ++++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 9ee86d68223..79690962388 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -359,6 +359,9 @@ impl Props { Props::None => None, } } + fn collision_message() -> &'static str { + "Using special syntax `with props` along with named prop is not allowed 1" + } } impl PeekValue for Props { @@ -393,17 +396,13 @@ impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - loop { - match HtmlProp::peek(input.cursor()) { - Some(()) => props.push(input.parse::()?), - None => { - if input.cursor().token_stream().to_string().contains("with") { - return Err(input.error("Using special syntax [with props] along with named prop is not allowed")); - }; - break; - } - } + while HtmlProp::peek(input.cursor()).is_some() { + props.push(input.parse::()?); } + + if input.cursor().token_stream().to_string().contains("with") { + return Err(input.error(Props::collision_message())); + }; let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); let node_ref = ref_position.map(|i| props.remove(i).value); @@ -462,7 +461,7 @@ impl Parse for WithProps { } else { return Err(syn::Error::new_spanned( &prop.label, - "Using special syntax [with props] along with named prop is not allowed", + Props::collision_message(), )); } } From a056c894d7e55ff0a26715161c17b437995159a8 Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Feb 2020 20:45:06 +0100 Subject: [PATCH 09/38] remove debug flag --- crates/macro/src/html_tree/html_component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 79690962388..e2a319de888 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -360,7 +360,7 @@ impl Props { } } fn collision_message() -> &'static str { - "Using special syntax `with props` along with named prop is not allowed 1" + "Using special syntax `with props` along with named prop is not allowed" } } From e0b06845737d1984dc7e0000ba4ebe74aea7386b Mon Sep 17 00:00:00 2001 From: Serhii Date: Mon, 24 Feb 2020 20:46:09 +0100 Subject: [PATCH 10/38] update --- crates/macro/src/html_tree/html_component.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index e2a319de888..da7b247095c 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -399,7 +399,6 @@ impl Parse for ListProps { while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); } - if input.cursor().token_stream().to_string().contains("with") { return Err(input.error(Props::collision_message())); }; @@ -445,8 +444,8 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { - let token = input.parse::()?; - if token != "with" { + let with = input.parse::()?; + if with != "with" { return Err(input.error("expected to find `with` token")); } let props = input.parse::()?; From bc3b08c7ef0f80c2a8515894725d3741118c1d7d Mon Sep 17 00:00:00 2001 From: Serhii Date: Tue, 25 Feb 2020 19:18:08 +0100 Subject: [PATCH 11/38] add stderr --- tests/macro/html-component-fail.stderr | 106 ++++++++++++++----------- 1 file changed, 59 insertions(+), 47 deletions(-) diff --git a/tests/macro/html-component-fail.stderr b/tests/macro/html-component-fail.stderr index 49d6cc305ef..64b27e2350d 100644 --- a/tests/macro/html-component-fail.stderr +++ b/tests/macro/html-component-fail.stderr @@ -36,7 +36,7 @@ error: unexpected token 58 | html! { }; | ^^^ -error: unexpected token +error: Using special syntax `with props` along with named prop is not allowed --> $DIR/html-component-fail.rs:59:27 | 59 | html! { }; @@ -48,60 +48,72 @@ error: unexpected token 61 | html! { }; | ^^ +error: Using special syntax `with props` along with named prop is not allowed + --> $DIR/html-component-fail.rs:62:28 + | +62 | html! { }; + | ^^^^ + +error: Using special syntax `with props` along with named prop is not allowed + --> $DIR/html-component-fail.rs:63:31 + | +63 | html! { }; + | ^^^^^ + error: expected identifier - --> $DIR/html-component-fail.rs:62:20 + --> $DIR/html-component-fail.rs:64:20 | -62 | html! { }; +64 | html! { }; | ^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:63:20 + --> $DIR/html-component-fail.rs:65:20 | -63 | html! { }; +65 | html! { }; | ^^^^^^^^^^^^^^^^^ error: unexpected end of input, expected expression - --> $DIR/html-component-fail.rs:65:5 + --> $DIR/html-component-fail.rs:67:5 | -65 | html! { }; +67 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: too many refs set - --> $DIR/html-component-fail.rs:70:33 + --> $DIR/html-component-fail.rs:72:33 | -70 | html! { }; +72 | html! { }; | ^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:73:13 + --> $DIR/html-component-fail.rs:75:13 | -73 | html! { }; +75 | html! { }; | ^^^^^^^^ error: this open tag has no corresponding close tag - --> $DIR/html-component-fail.rs:74:13 + --> $DIR/html-component-fail.rs:76:13 | -74 | html! { }; +76 | html! { }; | ^^^^^^^ error: only one root html element allowed - --> $DIR/html-component-fail.rs:75:28 + --> $DIR/html-component-fail.rs:77:28 | -75 | html! { }; +77 | html! { }; | ^^^^^^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:84:30 + --> $DIR/html-component-fail.rs:86:30 | -84 | html! { > }; +86 | html! { > }; | ^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:85:30 + --> $DIR/html-component-fail.rs:87:30 | -85 | html! { >>> }; +87 | html! { >>> }; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `blah` in this scope @@ -111,26 +123,26 @@ error[E0425]: cannot find value `blah` in this scope | ^^^^ not found in this scope error[E0609]: no field `unknown` on type `ChildProperties` - --> $DIR/html-component-fail.rs:64:20 + --> $DIR/html-component-fail.rs:66:20 | -64 | html! { }; +66 | html! { }; | ^^^^^^^ unknown field | = note: available fields are: `string`, `int` error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:64:20 + --> $DIR/html-component-fail.rs:66:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `unknown` not found for this ... -64 | html! { }; +66 | html! { }; | ^^^^^^^ method not found in `ChildPropertiesBuilder` 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 + --> $DIR/html-component-fail.rs:68:33 | -66 | html! { }; +68 | html! { }; | ^^ the trait `yew::virtual_dom::Transformer<(), std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -142,9 +154,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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 + --> $DIR/html-component-fail.rs:69:33 | -67 | html! { }; +69 | html! { }; | ^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -156,9 +168,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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 + --> $DIR/html-component-fail.rs:70:33 | -68 | html! { }; +70 | html! { }; | ^^^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -170,15 +182,15 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0308]: mismatched types - --> $DIR/html-component-fail.rs:69:30 + --> $DIR/html-component-fail.rs:71:30 | -69 | html! { }; +71 | html! { }; | ^^ expected struct `yew::html::NodeRef`, found `()` error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer` is not satisfied - --> $DIR/html-component-fail.rs:71:24 + --> $DIR/html-component-fail.rs:73:24 | -71 | html! { }; +73 | html! { }; | ^^^^ the trait `yew::virtual_dom::Transformer` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -190,51 +202,51 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:72:20 + --> $DIR/html-component-fail.rs:74:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `string` not found for this ... -72 | html! { }; +74 | html! { }; | ^^^^^^ method not found in `ChildPropertiesBuilder` error[E0599]: no method named `children` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:76:5 + --> $DIR/html-component-fail.rs:78:5 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `children` not found for this ... -76 | html! { { "Not allowed" } }; +78 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:78:5 + --> $DIR/html-component-fail.rs:80:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -78 | html! { }; +80 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:79:5 + --> $DIR/html-component-fail.rs:81:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -79 | html! { }; +81 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From<&str>` is not satisfied - --> $DIR/html-component-fail.rs:80:5 + --> $DIR/html-component-fail.rs:82:5 | -80 | html! { { "Not allowed" } }; +82 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `&str` @@ -242,9 +254,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:81:5 + --> $DIR/html-component-fail.rs:83:5 | -81 | html! { <> }; +83 | html! { <> }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` @@ -252,9 +264,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:82:5 + --> $DIR/html-component-fail.rs:84:5 | -82 | html! { }; +84 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` From 69f0e0a372496a32600ce8e511eeed9f58df391d Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 26 Feb 2020 22:30:19 +0100 Subject: [PATCH 12/38] update condition --- crates/macro/src/html_tree/html_component.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index da7b247095c..893a23615c4 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -396,12 +396,21 @@ impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); + loop { + let token = input.cursor(); + + if let Some(ident) = token.ident() { + if ident.0 == "with" { + return Err(input.error(Props::collision_message())); + } + } + + if HtmlProp::peek(token).is_some() { + props.push(input.parse::()?); + } else { + break; + } } - if input.cursor().token_stream().to_string().contains("with") { - return Err(input.error(Props::collision_message())); - }; let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); let node_ref = ref_position.map(|i| props.remove(i).value); From 8ea567cbe2aadce7c5acfaf00289bfce5aebb508 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 09:26:07 +0100 Subject: [PATCH 13/38] CR fix --- crates/macro/src/html_tree/html_component.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 893a23615c4..e09a4191e19 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -396,19 +396,13 @@ impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - loop { - let token = input.cursor(); - - if let Some(ident) = token.ident() { - if ident.0 == "with" { - return Err(input.error(Props::collision_message())); - } - } + while HtmlProp::peek(input.cursor()).is_some() { + props.push(input.parse::()?); + } - if HtmlProp::peek(token).is_some() { - props.push(input.parse::()?); - } else { - break; + if let Some(ident) = input.cursor().ident() { + if ident.0 == "with" { + return Err(input.error(Props::collision_message())); } } From 81edf1bac3ab34f648936c9864cf7725032e5c3b Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 09:29:56 +0100 Subject: [PATCH 14/38] remove empty line --- crates/macro/src/html_tree/html_component.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index e09a4191e19..e7a2f13f83c 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -395,7 +395,6 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); } From ae76a3827b3d923b51b8b085a7e4c75d789df74f Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 09:30:24 +0100 Subject: [PATCH 15/38] update --- crates/macro/src/html_tree/html_component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index e7a2f13f83c..9421580b851 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -395,7 +395,7 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { + while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); } From 3546d81b8ef9c8850afa85d9f1132fb7ac1a061a Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 18:33:42 +0100 Subject: [PATCH 16/38] update error message --- crates/macro/src/html_tree/html_component.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 9421580b851..0abe5d704d2 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -360,7 +360,7 @@ impl Props { } } fn collision_message() -> &'static str { - "Using special syntax `with props` along with named prop is not allowed" + "Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop" } } @@ -398,8 +398,8 @@ impl Parse for ListProps { while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); } - if let Some(ident) = input.cursor().ident() { + println!("IDENT {:?}", ident.0); if ident.0 == "with" { return Err(input.error(Props::collision_message())); } @@ -408,6 +408,7 @@ impl Parse for ListProps { let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); let node_ref = ref_position.map(|i| props.remove(i).value); for prop in &props { + println!("PROP {}", prop.label.to_string()); if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } @@ -470,3 +471,4 @@ impl Parse for WithProps { Ok(WithProps { props, node_ref }) } } + From b0cef0201ec0bef255e2a5556bb07683d0a39826 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 19:27:41 +0100 Subject: [PATCH 17/38] wip --- crates/macro/src/html_tree/html_component.rs | 38 +++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 0abe5d704d2..a17d5863ee9 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -452,23 +452,43 @@ impl Parse for WithProps { return Err(input.error("expected to find `with` token")); } let props = input.parse::()?; + println!("IDENT {}", props); + let _ = input.parse::(); // Check for the ref tag after `with` let mut node_ref = None; if let Some(ident) = input.cursor().ident() { - let prop = input.parse::()?; - if ident.0 == "ref" { - node_ref = Some(prop.value); - } else { - return Err(syn::Error::new_spanned( - &prop.label, - Props::collision_message(), - )); + if ident.0 == "ref" { + // node_ref = Some(prop.value); + } + let mut arr: Vec = Vec::new(); + + while HtmlProp::peek(input.cursor()).is_some() { + arr.push(input.parse::()?); } + let ref_position = arr.iter().position(|p| p.label.to_string() == "ref"); + node_ref = ref_position.map(|i| arr.remove(i).value); + + for prop in &arr { + println!("PROP {}", prop.label.to_string()); + if prop.label.to_string() == "ref" { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } + } + println!("ARR {:?}", ref_position); + + // let prop = input.parse::()?; + // if ident.0 == "ref" { + // node_ref = Some(prop.value); + // } else { + // return Err(syn::Error::new_spanned( + // &prop.label, + // Props::collision_message(), + // )); + // } } Ok(WithProps { props, node_ref }) } } - From 9c69526936fce170b98b3fd2c05c0871fee4ec78 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 21:13:49 +0100 Subject: [PATCH 18/38] work --- crates/macro/src/html_tree/html_component.rs | 42 ++++++++------------ tests/macro/html-component-fail.rs | 42 +++++++++++++++----- 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index a17d5863ee9..f07279d3308 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -452,41 +452,33 @@ impl Parse for WithProps { return Err(input.error("expected to find `with` token")); } let props = input.parse::()?; - println!("IDENT {}", props); let _ = input.parse::(); // Check for the ref tag after `with` let mut node_ref = None; - if let Some(ident) = input.cursor().ident() { - if ident.0 == "ref" { - // node_ref = Some(prop.value); - } - let mut arr: Vec = Vec::new(); + if input.cursor().ident().is_some() { + let mut flag = 0; while HtmlProp::peek(input.cursor()).is_some() { - arr.push(input.parse::()?); - } - let ref_position = arr.iter().position(|p| p.label.to_string() == "ref"); - node_ref = ref_position.map(|i| arr.remove(i).value); - - for prop in &arr { - println!("PROP {}", prop.label.to_string()); + let prop = input.parse::()?; if prop.label.to_string() == "ref" { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + flag += 1; + if flag >=2 { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } + if !node_ref.is_some() { + node_ref = Some(prop.value); + } + } else { + return Err(syn::Error::new_spanned( + &prop.label, + Props::collision_message(), + )); } } - println!("ARR {:?}", ref_position); - - // let prop = input.parse::()?; - // if ident.0 == "ref" { - // node_ref = Some(prop.value); - // } else { - // return Err(syn::Error::new_spanned( - // &prop.label, - // Props::collision_message(), - // )); - // } + + } Ok(WithProps { props, node_ref }) diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index b67e79fc40f..a54e7883ca1 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -15,9 +15,15 @@ impl Component for Child { type Message = (); type Properties = ChildProperties; - fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } - fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } - fn view(&self) -> Html { unimplemented!() } + fn create(_: Self::Properties, _: ComponentLink) -> Self { + unimplemented!() + } + fn update(&mut self, _: Self::Message) -> ShouldRender { + unimplemented!() + } + fn view(&self) -> Html { + unimplemented!() + } } #[derive(Clone, Properties)] @@ -31,9 +37,15 @@ impl Component for ChildContainer { type Message = (); type Properties = ChildContainerProperties; - fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } - fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } - fn view(&self) -> Html { unimplemented!() } + fn create(_: Self::Properties, _: ComponentLink) -> Self { + unimplemented!() + } + fn update(&mut self, _: Self::Message) -> ShouldRender { + unimplemented!() + } + fn view(&self) -> Html { + unimplemented!() + } } pub struct Generic { @@ -44,9 +56,15 @@ impl Component for Generic { type Message = (); type Properties = (); - fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } - fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } - fn view(&self) -> Html { unimplemented!() } + fn create(_: Self::Properties, _: ComponentLink) -> Self { + unimplemented!() + } + fn update(&mut self, _: Self::Message) -> ShouldRender { + unimplemented!() + } + fn view(&self) -> Html { + unimplemented!() + } } fn compile_fail() { @@ -56,6 +74,12 @@ fn compile_fail() { html! { }; html! { }; html! { }; + html! { }; + html! { }; + html! { }; + html! { }; + html! { }; + html! { }; html! { }; html! { }; html! { }; From 145393a661b47d05c76bf739fb0a8ccfc033fa76 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 21:15:55 +0100 Subject: [PATCH 19/38] unchange clippy --- tests/macro/html-component-fail.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index a54e7883ca1..38bc357b0a5 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -37,15 +37,9 @@ impl Component for ChildContainer { type Message = (); type Properties = ChildContainerProperties; - fn create(_: Self::Properties, _: ComponentLink) -> Self { - unimplemented!() - } - fn update(&mut self, _: Self::Message) -> ShouldRender { - unimplemented!() - } - fn view(&self) -> Html { - unimplemented!() - } + fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } + fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } + fn view(&self) -> Html { unimplemented!() } } pub struct Generic { From 6f307f9969df3e184386489f5d087643de8076f4 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 21:17:59 +0100 Subject: [PATCH 20/38] update --- tests/macro/html-component-fail.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index 38bc357b0a5..dc2a14833d1 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -15,15 +15,9 @@ impl Component for Child { type Message = (); type Properties = ChildProperties; - fn create(_: Self::Properties, _: ComponentLink) -> Self { - unimplemented!() - } - fn update(&mut self, _: Self::Message) -> ShouldRender { - unimplemented!() - } - fn view(&self) -> Html { - unimplemented!() - } + fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } + fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } + fn view(&self) -> Html { unimplemented!() } } #[derive(Clone, Properties)] @@ -50,15 +44,9 @@ impl Component for Generic { type Message = (); type Properties = (); - fn create(_: Self::Properties, _: ComponentLink) -> Self { - unimplemented!() - } - fn update(&mut self, _: Self::Message) -> ShouldRender { - unimplemented!() - } - fn view(&self) -> Html { - unimplemented!() - } + fn create(_: Self::Properties, _: ComponentLink) -> Self { unimplemented!() } + fn update(&mut self, _: Self::Message) -> ShouldRender { unimplemented!() } + fn view(&self) -> Html { unimplemented!() } } fn compile_fail() { From f7681e5574ec019ce0c464f615798edff27e2d16 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 21:22:08 +0100 Subject: [PATCH 21/38] remove logs --- tests/macro/html-component-fail.stderr | 156 +++++++++++++++---------- 1 file changed, 96 insertions(+), 60 deletions(-) diff --git a/tests/macro/html-component-fail.stderr b/tests/macro/html-component-fail.stderr index 64b27e2350d..f041677fc9f 100644 --- a/tests/macro/html-component-fail.stderr +++ b/tests/macro/html-component-fail.stderr @@ -30,119 +30,155 @@ error: this open tag has no corresponding close tag 57 | html! { }; | ^^^^^^^^^^^^^^^^^^^ -error: unexpected token +error: too many refs set --> $DIR/html-component-fail.rs:58:38 | 58 | html! { }; | ^^^ -error: Using special syntax `with props` along with named prop is not allowed - --> $DIR/html-component-fail.rs:59:27 +error: too many refs set + --> $DIR/html-component-fail.rs:59:38 + | +59 | html! { }; + | ^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:60:38 + | +60 | html! { }; + | ^^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:61:31 + | +61 | html! { }; + | ^^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:62:28 + | +62 | html! { }; + | ^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:63:35 + | +63 | html! { }; + | ^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:64:43 | -59 | html! { }; +64 | html! { }; + | ^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:65:27 + | +65 | html! { }; | ^^^^ error: unexpected token - --> $DIR/html-component-fail.rs:61:31 + --> $DIR/html-component-fail.rs:67:31 | -61 | html! { }; +67 | html! { }; | ^^ -error: Using special syntax `with props` along with named prop is not allowed - --> $DIR/html-component-fail.rs:62:28 +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:68:28 | -62 | html! { }; +68 | html! { }; | ^^^^ -error: Using special syntax `with props` along with named prop is not allowed - --> $DIR/html-component-fail.rs:63:31 +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:69:31 | -63 | html! { }; +69 | html! { }; | ^^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:64:20 + --> $DIR/html-component-fail.rs:70:20 | -64 | html! { }; +70 | html! { }; | ^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:65:20 + --> $DIR/html-component-fail.rs:71:20 | -65 | html! { }; +71 | html! { }; | ^^^^^^^^^^^^^^^^^ error: unexpected end of input, expected expression - --> $DIR/html-component-fail.rs:67:5 + --> $DIR/html-component-fail.rs:73:5 | -67 | html! { }; +73 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: too many refs set - --> $DIR/html-component-fail.rs:72:33 + --> $DIR/html-component-fail.rs:78:33 | -72 | html! { }; +78 | html! { }; | ^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:75:13 + --> $DIR/html-component-fail.rs:81:13 | -75 | html! { }; +81 | html! { }; | ^^^^^^^^ error: this open tag has no corresponding close tag - --> $DIR/html-component-fail.rs:76:13 + --> $DIR/html-component-fail.rs:82:13 | -76 | html! { }; +82 | html! { }; | ^^^^^^^ error: only one root html element allowed - --> $DIR/html-component-fail.rs:77:28 + --> $DIR/html-component-fail.rs:83:28 | -77 | html! { }; +83 | html! { }; | ^^^^^^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:86:30 + --> $DIR/html-component-fail.rs:92:30 | -86 | html! { > }; +92 | html! { > }; | ^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:87:30 + --> $DIR/html-component-fail.rs:93:30 | -87 | html! { >>> }; +93 | html! { >>> }; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `blah` in this scope - --> $DIR/html-component-fail.rs:60:25 + --> $DIR/html-component-fail.rs:66:25 | -60 | html! { }; +66 | html! { }; | ^^^^ not found in this scope error[E0609]: no field `unknown` on type `ChildProperties` - --> $DIR/html-component-fail.rs:66:20 + --> $DIR/html-component-fail.rs:72:20 | -66 | html! { }; +72 | html! { }; | ^^^^^^^ unknown field | = note: available fields are: `string`, `int` error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:66:20 + --> $DIR/html-component-fail.rs:72:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `unknown` not found for this ... -66 | html! { }; +72 | html! { }; | ^^^^^^^ method not found in `ChildPropertiesBuilder` 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:68:33 + --> $DIR/html-component-fail.rs:74:33 | -68 | html! { }; +74 | html! { }; | ^^ the trait `yew::virtual_dom::Transformer<(), std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -154,9 +190,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:69:33 + --> $DIR/html-component-fail.rs:75:33 | -69 | html! { }; +75 | html! { }; | ^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -168,9 +204,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:70:33 + --> $DIR/html-component-fail.rs:76:33 | -70 | html! { }; +76 | html! { }; | ^^^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -182,15 +218,15 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0308]: mismatched types - --> $DIR/html-component-fail.rs:71:30 + --> $DIR/html-component-fail.rs:77:30 | -71 | html! { }; +77 | html! { }; | ^^ expected struct `yew::html::NodeRef`, found `()` error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer` is not satisfied - --> $DIR/html-component-fail.rs:73:24 + --> $DIR/html-component-fail.rs:79:24 | -73 | html! { }; +79 | html! { }; | ^^^^ the trait `yew::virtual_dom::Transformer` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -202,51 +238,51 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:74:20 + --> $DIR/html-component-fail.rs:80:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `string` not found for this ... -74 | html! { }; +80 | html! { }; | ^^^^^^ method not found in `ChildPropertiesBuilder` error[E0599]: no method named `children` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:78:5 + --> $DIR/html-component-fail.rs:84:5 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `children` not found for this ... -78 | html! { { "Not allowed" } }; +84 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:80:5 + --> $DIR/html-component-fail.rs:86:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -80 | html! { }; +86 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:81:5 + --> $DIR/html-component-fail.rs:87:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -81 | html! { }; +87 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From<&str>` is not satisfied - --> $DIR/html-component-fail.rs:82:5 + --> $DIR/html-component-fail.rs:88:5 | -82 | html! { { "Not allowed" } }; +88 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `&str` @@ -254,9 +290,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:83:5 + --> $DIR/html-component-fail.rs:89:5 | -83 | html! { <> }; +89 | html! { <> }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` @@ -264,9 +300,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:84:5 + --> $DIR/html-component-fail.rs:90:5 | -84 | html! { }; +90 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` From 990437e7e84c82fcbce02f39d58a9bf93c002d62 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 21:23:13 +0100 Subject: [PATCH 22/38] println --- crates/macro/src/html_tree/html_component.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index f07279d3308..f540ec5a6f0 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -399,7 +399,6 @@ impl Parse for ListProps { props.push(input.parse::()?); } if let Some(ident) = input.cursor().ident() { - println!("IDENT {:?}", ident.0); if ident.0 == "with" { return Err(input.error(Props::collision_message())); } @@ -408,7 +407,6 @@ impl Parse for ListProps { let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); let node_ref = ref_position.map(|i| props.remove(i).value); for prop in &props { - println!("PROP {}", prop.label.to_string()); if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } @@ -477,8 +475,6 @@ impl Parse for WithProps { )); } } - - } Ok(WithProps { props, node_ref }) From f421174ac537918949c5e20656393f8b61f15fd7 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 22:04:20 +0100 Subject: [PATCH 23/38] format --- crates/macro/src/html_tree/html_component.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index f540ec5a6f0..0ea088d1b5f 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -456,13 +456,12 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; if input.cursor().ident().is_some() { - let mut flag = 0; while HtmlProp::peek(input.cursor()).is_some() { let prop = input.parse::()?; if prop.label.to_string() == "ref" { flag += 1; - if flag >=2 { + if flag >= 2 { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } if !node_ref.is_some() { From 23bdf725821842450af3fc2d31d446e390cec4be Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 22:27:17 +0100 Subject: [PATCH 24/38] clippy --- crates/macro/src/html_tree/html_component.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 0ea088d1b5f..3014ef4cbb1 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -464,7 +464,7 @@ impl Parse for WithProps { if flag >= 2 { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } - if !node_ref.is_some() { + if node_ref.is_none() { node_ref = Some(prop.value); } } else { From 62bb054aa9f50b7a9d38b792ec8201424002cce7 Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 27 Feb 2020 22:42:46 +0100 Subject: [PATCH 25/38] VERY WIP --- crates/macro/src/html_tree/html_component.rs | 65 ++++++++++++++------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 3014ef4cbb1..3da49413ba3 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -391,21 +391,30 @@ struct ListProps { props: Vec, node_ref: Option, } +pub fn custom(input: ParseStream) -> ParseResult> { + let mut props: Vec = Vec::new(); + while HtmlProp::peek(input.cursor()).is_some() { + props.push(input.parse::()?); + } + Ok(props) +} + +fn remove_refs(mut props: Vec) -> Option { + let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); + ref_position.map(|i| props.remove(i).value) +} impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); - } + let mut props = custom(input)?; + if let Some(ident) = input.cursor().ident() { if ident.0 == "with" { return Err(input.error(Props::collision_message())); } } - let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); - let node_ref = ref_position.map(|i| props.remove(i).value); + let node_ref = remove_refs(props); for prop in &props { if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); @@ -457,23 +466,39 @@ impl Parse for WithProps { let mut node_ref = None; if input.cursor().ident().is_some() { let mut flag = 0; - while HtmlProp::peek(input.cursor()).is_some() { - let prop = input.parse::()?; + let mut props = custom(input)?; + + let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); + let node_ref = ref_position.map(|i| props.remove(i).value); + for prop in &props { if prop.label.to_string() == "ref" { - flag += 1; - if flag >= 2 { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - if node_ref.is_none() { - node_ref = Some(prop.value); - } - } else { - return Err(syn::Error::new_spanned( - &prop.label, - Props::collision_message(), - )); + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); } } + + // while HtmlProp::peek(input.cursor()).is_some() { + // let prop = input.parse::()?; + // if prop.label.to_string() == "ref" { + // flag += 1; + // if flag >= 2 { + // return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + // } + // if node_ref.is_none() { + // node_ref = Some(prop.value); + // } + // } else { + // return Err(syn::Error::new_spanned( + // &prop.label, + // Props::collision_message(), + // )); + // } + // } } Ok(WithProps { props, node_ref }) From 8fdbc692b29214cc941ea19e9b4adbc462a4ad92 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 28 Feb 2020 19:11:27 +0100 Subject: [PATCH 26/38] error collect --- crates/macro/src/html_tree/html_component.rs | 114 ++++++++++++------- 1 file changed, 74 insertions(+), 40 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 3da49413ba3..ea1c864c78a 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -6,6 +6,7 @@ use boolinator::Boolinator; use proc_macro2::Span; use quote::{quote, quote_spanned, ToTokens}; use std::cmp::Ordering; +use std::collections::HashMap; use syn::buffer::Cursor; use syn::parse; use syn::parse::{Parse, ParseStream, Result as ParseResult}; @@ -391,22 +392,72 @@ struct ListProps { props: Vec, node_ref: Option, } -pub fn custom(input: ParseStream) -> ParseResult> { - let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); +impl ListProps { + fn collect_props(input: ParseStream) -> ParseResult> { + let mut props: Vec = Vec::new(); + while HtmlProp::peek(input.cursor()).is_some() { + props.push(input.parse::()?); + } + Ok(props) } - Ok(props) -} -fn remove_refs(mut props: Vec) -> Option { - let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); - ref_position.map(|i| props.remove(i).value) + fn remove_refs(mut props: Vec) -> ListProps { + let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); + let node_ref = ref_position.map(|i| props.remove(i).value); + ListProps { props, node_ref } + } + + fn apply_edge_cases(props: &Vec) -> Result<(), syn::Error> { + let mut map: HashMap<&str, Box Result<(), syn::Error>>> = HashMap::new(); + // Result, GetInterfaceError> + let ref_handler = |prop: HtmlProp| { + if prop.label.to_string() == "ref" { + Err(syn::Error::new_spanned(&prop.label, "too many refs set")) + } + Ok(()) + }; + + let type_handler = |prop: HtmlProp| { + if prop.label.to_string() == "type" { + Err(syn::Error::new_spanned(&prop.label, "expected identifier")) + } + Ok(()) + }; + + let unexpected_handler = |prop: HtmlProp| { + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + Ok(()) + }; + + map.insert("ref", Box::new(ref_handler)); + map.insert("type", Box::new(type_handler)); + map.insert("unexpected",Box::new(unexpected_handler)); + + props.iter().for_each(|prop|{ + + }) + + + for prop in props { + if prop.label.to_string() == "ref" { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + } + Ok(()) + } } impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - let mut props = custom(input)?; + let props = ListProps::collect_props(input)?; if let Some(ident) = input.cursor().ident() { if ident.0 == "with" { @@ -414,7 +465,11 @@ impl Parse for ListProps { } } - let node_ref = remove_refs(props); + let ListProps { + mut props, + node_ref, + } = ListProps::remove_refs(props); + for prop in &props { if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); @@ -465,40 +520,19 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; if input.cursor().ident().is_some() { - let mut flag = 0; - let mut props = custom(input)?; + let list_props = ListProps::remove_refs(ListProps::collect_props(input)?); + node_ref = list_props.node_ref; - let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); - let node_ref = ref_position.map(|i| props.remove(i).value); - for prop in &props { + for prop in &list_props.props { if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } else { + return Err(syn::Error::new_spanned( + &prop.label, + Props::collision_message(), + )); } } - - // while HtmlProp::peek(input.cursor()).is_some() { - // let prop = input.parse::()?; - // if prop.label.to_string() == "ref" { - // flag += 1; - // if flag >= 2 { - // return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - // } - // if node_ref.is_none() { - // node_ref = Some(prop.value); - // } - // } else { - // return Err(syn::Error::new_spanned( - // &prop.label, - // Props::collision_message(), - // )); - // } - // } } Ok(WithProps { props, node_ref }) From bf42a1a6fa959e7d364cb7259c0819165972686f Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 28 Feb 2020 20:24:09 +0100 Subject: [PATCH 27/38] refactor --- crates/macro/src/html_tree/html_component.rs | 85 ++++++++++---------- 1 file changed, 43 insertions(+), 42 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index ea1c864c78a..e65afdbbb0a 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -408,49 +408,57 @@ impl ListProps { } fn apply_edge_cases(props: &Vec) -> Result<(), syn::Error> { - let mut map: HashMap<&str, Box Result<(), syn::Error>>> = HashMap::new(); - // Result, GetInterfaceError> - let ref_handler = |prop: HtmlProp| { + let mut map: HashMap<&str, Box Result<_, syn::Error>>> = + HashMap::new(); + + let ref_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { if prop.label.to_string() == "ref" { - Err(syn::Error::new_spanned(&prop.label, "too many refs set")) + Err(syn::Error::new_spanned(&prop.label, "too many refs set")) + } else { + Ok(()) } - Ok(()) - }; + }; - let type_handler = |prop: HtmlProp| { + let type_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { if prop.label.to_string() == "type" { - Err(syn::Error::new_spanned(&prop.label, "expected identifier")) + Err(syn::Error::new_spanned(&prop.label, "expected identifier")) + } else { + Ok(()) } - Ok(()) }; - - let unexpected_handler = |prop: HtmlProp| { + + let unexpected_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + Err(syn::Error::new_spanned(&prop.label, "expected identifier")) + } else { + Ok(()) } - Ok(()) }; map.insert("ref", Box::new(ref_handler)); map.insert("type", Box::new(type_handler)); - map.insert("unexpected",Box::new(unexpected_handler)); - - props.iter().for_each(|prop|{ - - }) + map.insert("unexpected", Box::new(unexpected_handler)); + + let errors = props.iter().fold(vec![], |acc, prop: &HtmlProp| { + [ + acc, + ["ref", "type", "unexpected"] + .iter() + .map(|elem| match map.get(elem) { + Some(handler) => handler(prop), + None => Err(syn::Error::new_spanned(&prop.label, "something went wrong")), + }) + .filter(Result::is_err) + .collect::>>(), + ] + .concat() + }); - for prop in props { - if prop.label.to_string() == "ref" { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } + for error in errors { + return error; } + Ok(()) } } @@ -470,17 +478,7 @@ impl Parse for ListProps { node_ref, } = ListProps::remove_refs(props); - for prop in &props { - if prop.label.to_string() == "ref" { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - } + ListProps::apply_edge_cases(&props)?; // alphabetize props.sort_by(|a, b| { @@ -520,10 +518,13 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; if input.cursor().ident().is_some() { - let list_props = ListProps::remove_refs(ListProps::collect_props(input)?); - node_ref = list_props.node_ref; + let ListProps { + props: list_props, + node_ref: reference, + } = ListProps::remove_refs(ListProps::collect_props(input)?); + node_ref = reference; - for prop in &list_props.props { + for prop in &list_props { if prop.label.to_string() == "ref" { return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } else { From b9b2a6d0569e1e36f8ba39f3b29574c9e1342df2 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 28 Feb 2020 20:44:35 +0100 Subject: [PATCH 28/38] add second argument --- crates/macro/src/html_tree/html_component.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index e65afdbbb0a..aa40ac4896c 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -407,7 +407,7 @@ impl ListProps { ListProps { props, node_ref } } - fn apply_edge_cases(props: &Vec) -> Result<(), syn::Error> { + fn apply_edge_cases(props: &Vec, cases: &[&str]) -> Result<(), syn::Error> { let mut map: HashMap<&str, Box Result<_, syn::Error>>> = HashMap::new(); @@ -442,7 +442,7 @@ impl ListProps { let errors = props.iter().fold(vec![], |acc, prop: &HtmlProp| { [ acc, - ["ref", "type", "unexpected"] + cases .iter() .map(|elem| match map.get(elem) { Some(handler) => handler(prop), @@ -478,7 +478,7 @@ impl Parse for ListProps { node_ref, } = ListProps::remove_refs(props); - ListProps::apply_edge_cases(&props)?; + ListProps::apply_edge_cases(&props, &["ref"])?; // alphabetize props.sort_by(|a, b| { From ee82df4c032407f17dd921ebc72741ba04a7bf44 Mon Sep 17 00:00:00 2001 From: Serhii Date: Fri, 28 Feb 2020 22:06:09 +0100 Subject: [PATCH 29/38] format --- crates/macro/src/html_tree/html_component.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index aa40ac4896c..d61995948ad 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -454,7 +454,6 @@ impl ListProps { .concat() }); - for error in errors { return error; } From 6ee8610a6a292b0e7072409b6362f068cb7e7fae Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 29 Feb 2020 15:57:36 +0100 Subject: [PATCH 30/38] wip --- crates/macro/src/html_tree/html_component.rs | 118 +++++++------------ 1 file changed, 44 insertions(+), 74 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index d61995948ad..b8149b2bca2 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -363,14 +363,52 @@ impl Props { fn collision_message() -> &'static str { "Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop" } + + fn collect_props(input: ParseStream) -> ParseResult> { + let mut props: Vec = Vec::new(); + while HtmlProp::peek(input.cursor()).is_some() { + props.push(input.parse::()?); + } + Ok(props) + } + + fn remove_refs(mut props: Vec) -> ListProps { + let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); + let node_ref = ref_position.map(|i| props.remove(i).value); + ListProps { props, node_ref } + } + + fn handle_errors(props: &Vec) -> ParseResult<()> { + for prop in props { + if prop.label.to_string() == "ref" { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + } + Ok(()) + } } impl PeekValue for Props { fn peek(cursor: Cursor) -> Option { let (ident, _) = cursor.ident()?; + println!("PEEK {}", ident); + if ident == "ref" { + () + } + let prop_type = if ident == "with" { + println!("WITH PROPS {}", ident); + PropType::With } else { + println!("LIST PROPS {}", ident); + PropType::List }; @@ -392,92 +430,24 @@ struct ListProps { props: Vec, node_ref: Option, } -impl ListProps { - fn collect_props(input: ParseStream) -> ParseResult> { - let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); - } - Ok(props) - } - - fn remove_refs(mut props: Vec) -> ListProps { - let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); - let node_ref = ref_position.map(|i| props.remove(i).value); - ListProps { props, node_ref } - } - - fn apply_edge_cases(props: &Vec, cases: &[&str]) -> Result<(), syn::Error> { - let mut map: HashMap<&str, Box Result<_, syn::Error>>> = - HashMap::new(); - - let ref_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { - if prop.label.to_string() == "ref" { - Err(syn::Error::new_spanned(&prop.label, "too many refs set")) - } else { - Ok(()) - } - }; - - let type_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { - if prop.label.to_string() == "type" { - Err(syn::Error::new_spanned(&prop.label, "expected identifier")) - } else { - Ok(()) - } - }; - - let unexpected_handler = |prop: &HtmlProp| -> Result<_, syn::Error> { - if !prop.label.extended.is_empty() { - Err(syn::Error::new_spanned(&prop.label, "expected identifier")) - } else { - Ok(()) - } - }; - - map.insert("ref", Box::new(ref_handler)); - map.insert("type", Box::new(type_handler)); - map.insert("unexpected", Box::new(unexpected_handler)); - - let errors = props.iter().fold(vec![], |acc, prop: &HtmlProp| { - [ - acc, - cases - .iter() - .map(|elem| match map.get(elem) { - Some(handler) => handler(prop), - None => Err(syn::Error::new_spanned(&prop.label, "something went wrong")), - }) - .filter(Result::is_err) - .collect::>>(), - ] - .concat() - }); - - for error in errors { - return error; - } - - Ok(()) - } -} impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - let props = ListProps::collect_props(input)?; + let props = Props::collect_props(input)?; if let Some(ident) = input.cursor().ident() { if ident.0 == "with" { - return Err(input.error(Props::collision_message())); + println!("PROPS {}", props[0].label.to_string()); + return Err(input.error(ident.0)); } } let ListProps { mut props, node_ref, - } = ListProps::remove_refs(props); + } = Props::remove_refs(props); - ListProps::apply_edge_cases(&props, &["ref"])?; + Props::handle_errors(&props)?; // alphabetize props.sort_by(|a, b| { @@ -520,7 +490,7 @@ impl Parse for WithProps { let ListProps { props: list_props, node_ref: reference, - } = ListProps::remove_refs(ListProps::collect_props(input)?); + } = Props::remove_refs(Props::collect_props(input)?); node_ref = reference; for prop in &list_props { From 0ff9648c16d54d697a9ddc038b61559e8d00e6b5 Mon Sep 17 00:00:00 2001 From: Serhii Date: Sat, 29 Feb 2020 22:41:18 +0100 Subject: [PATCH 31/38] wip with main parsser --- crates/macro/src/html_tree/html_component.rs | 175 +++++++++++++++---- src/virtual_dom/vcomp.rs | 26 +-- 2 files changed, 154 insertions(+), 47 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index b8149b2bca2..77e71251382 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -364,7 +364,7 @@ impl Props { "Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop" } - fn collect_props(input: ParseStream) -> ParseResult> { + fn collect_props(input: ParseStream<'_>) -> ParseResult> { let mut props: Vec = Vec::new(); while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); @@ -378,18 +378,121 @@ impl Props { ListProps { props, node_ref } } - fn handle_errors(props: &Vec) -> ParseResult<()> { + fn return_type(input: ParseStream) -> Option { + loop { + if let Some((token, _)) = input.cursor().ident() { + input.parse::(); + println!("Token {}", token); + // it will skip all `ref's` + if token != "with" && token != "ref" { + return Some(PropType::List); + } + if token == "with" { + return Some(PropType::With); + } + } + } + } + + fn main_parser(input: ParseStream) -> ParseResult> { + let mut props: Vec = Vec::new(); + let mut with_exist = false; + let mut ref_counter = 0; + + loop { + println!("STREAM {}", input.cursor().token_stream()); + if let Some((with, _)) = input.cursor().ident() { + println!("START IDENT {}", with); + } + let prop = input.parse::(); + if let Some((with, _)) = input.cursor().ident() { + if !with_exist && with == "with" { + with_exist = true + } + } + match prop { + Ok(v) => { + if v.label.to_string() == "ref" { + ref_counter = ref_counter + 1; + + if ref_counter > 1 { + break; + // return Err(syn::Error::new_spanned(&v.label, "too many refs set")); + } + } + + println!("PUSH VALUE {}", v.label.to_string()); + props.push(v); + println!("PUSH VALUE {}", props.len()); + } + Err(e) => { + println!("ERROR {}", input.cursor().token_stream()); + if let Some(value) = input.cursor().ident() { + println!("ERROR IDENT{}", value.0); + } + break; + } + } + } + println!( + "LENGTH {}, {}, counter:: {}", + props.len(), + with_exist, + ref_counter + ); + + Ok(props) + } + + fn get_type(input: ParseStream) -> ParseResult> { + // let mut qwerty = Props::main_parser(input.clone()); //Props::peek(input.cursor()); + let props_type = Props::return_type(&input.fork()); //Props::peek(input.cursor()); + match props_type { + Some(PropType::With)=>println!("with"), + Some(PropType::List)=>println!("list"), + None=>println!("none"), + + } + let props = Props::collect_props(input)?; + println!("STREAM {}", input.cursor().token_stream()); + // if !props.is_empty(){ + // if props[0].label.to_string() == "ref" { + + // } + // } + + Props::handle_errors(&props, &props_type)?; + + Ok(props_type) + } + + fn handle_errors(props: &Vec, prop_type: &Option) -> ParseResult<()> { + let mut ref_indicator: u8 = 0; for prop in props { if prop.label.to_string() == "ref" { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + ref_indicator = ref_indicator + 1; + if ref_indicator > 1 { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + } } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + match prop_type { + Some(PropType::List) => { + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + } + Some(PropType::With) => { + if ref_indicator == 0 { + return Err(syn::Error::new_spanned(&prop.label, ref_indicator)); + } + } + None => (), } } + Ok(()) } } @@ -397,18 +500,13 @@ impl Props { impl PeekValue for Props { fn peek(cursor: Cursor) -> Option { let (ident, _) = cursor.ident()?; - println!("PEEK {}", ident); - if ident == "ref" { - () - } let prop_type = if ident == "with" { - println!("WITH PROPS {}", ident); + println!("IDENT {}", ident); PropType::With } else { - println!("LIST PROPS {}", ident); - + println!("LIST"); PropType::List }; @@ -418,7 +516,7 @@ impl PeekValue for Props { impl Parse for Props { fn parse(input: ParseStream) -> ParseResult { - match Props::peek(input.cursor()) { + match Props::get_type(input)? { Some(PropType::List) => input.parse().map(|l| Props::List(Box::new(l))), Some(PropType::With) => input.parse().map(|w| Props::With(Box::new(w))), None => Ok(Props::None), @@ -433,21 +531,16 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - let props = Props::collect_props(input)?; - - if let Some(ident) = input.cursor().ident() { - if ident.0 == "with" { - println!("PROPS {}", props[0].label.to_string()); - return Err(input.error(ident.0)); - } - } + println!("LIST"); + match Props::peek(input.cursor()) { + Some(PropType::With) => return Err(input.error(Props::collision_message())), + _ => (), + }; let ListProps { mut props, node_ref, - } = Props::remove_refs(props); - - Props::handle_errors(&props)?; + } = Props::remove_refs(Props::collect_props(input)?); // alphabetize props.sort_by(|a, b| { @@ -476,6 +569,8 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { + println!("WITH"); + let with = input.parse::()?; if with != "with" { return Err(input.error("expected to find `with` token")); @@ -486,21 +581,33 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; + println!("IS 1 SOME {}", input.cursor().token_stream()); + if input.cursor().ident().is_some() { + println!("IS SOME"); let ListProps { props: list_props, node_ref: reference, } = Props::remove_refs(Props::collect_props(input)?); node_ref = reference; - for prop in &list_props { - if prop.label.to_string() == "ref" { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + // for prop in &list_props { + // if prop.label.to_string() == "ref" { + // return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); + // } else { + // return Err(syn::Error::new_spanned( + // &prop.label, + // Props::collision_message(), + // )); + // } + // } + if let Some(ident) = input.cursor().ident() { + let prop = input.parse::()?; + println!("IDENT !!! {}", ident.0); + if ident.0 == "ref" { + node_ref = Some(prop.value); } else { - return Err(syn::Error::new_spanned( - &prop.label, - Props::collision_message(), - )); + return Err(syn::Error::new_spanned(&prop.label, "unexpected token")); } } } diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index c7674dbe8d8..4ff2f22bc13 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -323,21 +323,21 @@ mod tests { #[test] fn set_properties_to_component() { - html! { - - }; + // html! { + // + // }; - html! { - - }; + // html! { + // + // }; - html! { - - }; + // html! { + // + // }; - html! { - - }; + // html! { + // + // }; let props = Props { field_1: 1, @@ -345,7 +345,7 @@ mod tests { }; html! { - + }; } } From 53bd8ce0f9071d44bfa9eee39d517cdbd6050e3c Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 1 Mar 2020 19:42:41 +0100 Subject: [PATCH 32/38] wip --- crates/macro/src/html_tree/html_component.rs | 92 ++++++++++---------- src/virtual_dom/vcomp.rs | 2 +- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 77e71251382..9ccad9b51df 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -364,7 +364,7 @@ impl Props { "Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop" } - fn collect_props(input: ParseStream<'_>) -> ParseResult> { + fn collect_props(input: ParseStream) -> ParseResult> { let mut props: Vec = Vec::new(); while HtmlProp::peek(input.cursor()).is_some() { props.push(input.parse::()?); @@ -378,20 +378,34 @@ impl Props { ListProps { props, node_ref } } - fn return_type(input: ParseStream) -> Option { - loop { - if let Some((token, _)) = input.cursor().ident() { - input.parse::(); - println!("Token {}", token); - // it will skip all `ref's` - if token != "with" && token != "ref" { - return Some(PropType::List); - } - if token == "with" { - return Some(PropType::With); - } + fn return_type(input: ParseStream) -> ParseResult> { + let stream = input.fork(); + let mut is_with = false; + let mut ref_counter = 0; + let mut other_props = vec![]; + + while let Some((token, _)) = stream.cursor().ident() { + let _ = stream.parse::(); + if token != "with" && token != "ref" { + other_props.push(token.clone()); + // return Some(PropType::List); + } + if token == "with" { + is_with = true; + // return Some(PropType::With); + } + if token == "ref" { + ref_counter = ref_counter + 1; } } + + + + println!( + "IS_WITH::{}, REF_COUNTER::{}, OTHER_PROPS::{:?}", + is_with, ref_counter, other_props + ); + Ok(Some(PropType::List)) } fn main_parser(input: ParseStream) -> ParseResult> { @@ -445,21 +459,20 @@ impl Props { } fn get_type(input: ParseStream) -> ParseResult> { - // let mut qwerty = Props::main_parser(input.clone()); //Props::peek(input.cursor()); - let props_type = Props::return_type(&input.fork()); //Props::peek(input.cursor()); - match props_type { - Some(PropType::With)=>println!("with"), - Some(PropType::List)=>println!("list"), - None=>println!("none"), + // let mut qwerty = Props::main_parser(input.clone()); //Props::peek(input.cursor()); + let props_type = match Props::return_type(input) { + Ok(value) => value, + Err(e) => None + }; + + match props_type { + Some(PropType::With) => println!("props_type::with"), + Some(PropType::List) => println!("props_type::list"), + None => println!("none"), } let props = Props::collect_props(input)?; - println!("STREAM {}", input.cursor().token_stream()); - // if !props.is_empty(){ - // if props[0].label.to_string() == "ref" { - - // } - // } + // println!("STREAM {}", props[0].label.to_string()); Props::handle_errors(&props, &props_type)?; @@ -468,6 +481,7 @@ impl Props { fn handle_errors(props: &Vec, prop_type: &Option) -> ParseResult<()> { let mut ref_indicator: u8 = 0; + println!("PROPS {}", props.len()); for prop in props { if prop.label.to_string() == "ref" { ref_indicator = ref_indicator + 1; @@ -502,11 +516,8 @@ impl PeekValue for Props { let (ident, _) = cursor.ident()?; let prop_type = if ident == "with" { - println!("IDENT {}", ident); - PropType::With } else { - println!("LIST"); PropType::List }; @@ -531,7 +542,6 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - println!("LIST"); match Props::peek(input.cursor()) { Some(PropType::With) => return Err(input.error(Props::collision_message())), _ => (), @@ -569,8 +579,6 @@ struct WithProps { impl Parse for WithProps { fn parse(input: ParseStream) -> ParseResult { - println!("WITH"); - let with = input.parse::()?; if with != "with" { return Err(input.error("expected to find `with` token")); @@ -581,29 +589,23 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; - println!("IS 1 SOME {}", input.cursor().token_stream()); + println!( + "WITH PROPS STREAM::{}, is_some {}", + input.cursor().token_stream(), + input.cursor().ident().is_some() + ); if input.cursor().ident().is_some() { - println!("IS SOME"); let ListProps { - props: list_props, node_ref: reference, + .. } = Props::remove_refs(Props::collect_props(input)?); node_ref = reference; + println!("IS SOME {}", input.cursor().ident().is_some()); - // for prop in &list_props { - // if prop.label.to_string() == "ref" { - // return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - // } else { - // return Err(syn::Error::new_spanned( - // &prop.label, - // Props::collision_message(), - // )); - // } - // } if let Some(ident) = input.cursor().ident() { let prop = input.parse::()?; - println!("IDENT !!! {}", ident.0); + println!("WITJ IF SOME IDENT {}", ident.0); if ident.0 == "ref" { node_ref = Some(prop.value); } else { diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index 4ff2f22bc13..adf8b073355 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -345,7 +345,7 @@ mod tests { }; html! { - + }; } } From a619b5baf52110d044526c6fa22dda5a2ccc996a Mon Sep 17 00:00:00 2001 From: Serhii Date: Sun, 1 Mar 2020 21:33:59 +0100 Subject: [PATCH 33/38] receive unexpected error --- crates/macro/src/html_tree/html_component.rs | 157 +++++-------------- src/virtual_dom/vcomp.rs | 2 +- 2 files changed, 40 insertions(+), 119 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 9ccad9b51df..39a8d45e05f 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -378,137 +378,63 @@ impl Props { ListProps { props, node_ref } } - fn return_type(input: ParseStream) -> ParseResult> { + fn return_type(input: ParseStream) -> ParseResult { let stream = input.fork(); let mut is_with = false; let mut ref_counter = 0; - let mut other_props = vec![]; + let mut props_counter = 0; while let Some((token, _)) = stream.cursor().ident() { - let _ = stream.parse::(); - if token != "with" && token != "ref" { - other_props.push(token.clone()); - // return Some(PropType::List); - } + let prop_value = stream.parse::(); if token == "with" { is_with = true; - // return Some(PropType::With); - } - if token == "ref" { - ref_counter = ref_counter + 1; - } - } - - - - println!( - "IS_WITH::{}, REF_COUNTER::{}, OTHER_PROPS::{:?}", - is_with, ref_counter, other_props - ); - Ok(Some(PropType::List)) - } - - fn main_parser(input: ParseStream) -> ParseResult> { - let mut props: Vec = Vec::new(); - let mut with_exist = false; - let mut ref_counter = 0; - - loop { - println!("STREAM {}", input.cursor().token_stream()); - if let Some((with, _)) = input.cursor().ident() { - println!("START IDENT {}", with); } - let prop = input.parse::(); - if let Some((with, _)) = input.cursor().ident() { - if !with_exist && with == "with" { - with_exist = true - } + if is_with && (props_counter - ref_counter) > 0 { + return Err(syn::Error::new_spanned(&token, Props::collision_message())); } - match prop { - Ok(v) => { - if v.label.to_string() == "ref" { - ref_counter = ref_counter + 1; - - if ref_counter > 1 { - break; - // return Err(syn::Error::new_spanned(&v.label, "too many refs set")); - } + if let Ok(prop) = prop_value { + if prop.label.to_string() == "ref" { + ref_counter = ref_counter + 1; + if ref_counter > 1 { + return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); } - - println!("PUSH VALUE {}", v.label.to_string()); - props.push(v); - println!("PUSH VALUE {}", props.len()); - } - Err(e) => { - println!("ERROR {}", input.cursor().token_stream()); - if let Some(value) = input.cursor().ident() { - println!("ERROR IDENT{}", value.0); + } else { + if is_with { + return Err(syn::Error::new_spanned(&token, Props::collision_message())); } - break; } + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } + props_counter = props_counter + 1; } } - println!( - "LENGTH {}, {}, counter:: {}", - props.len(), - with_exist, - ref_counter - ); - - Ok(props) + if is_with { + Ok(PropType::With) + } else { + Ok(PropType::List) + } } fn get_type(input: ParseStream) -> ParseResult> { - // let mut qwerty = Props::main_parser(input.clone()); //Props::peek(input.cursor()); let props_type = match Props::return_type(input) { - Ok(value) => value, - Err(e) => None + Ok(props) => Some(props), + Err(_) => None, }; - match props_type { Some(PropType::With) => println!("props_type::with"), Some(PropType::List) => println!("props_type::list"), None => println!("none"), } - let props = Props::collect_props(input)?; - // println!("STREAM {}", props[0].label.to_string()); - - Props::handle_errors(&props, &props_type)?; + let _ = Props::collect_props(input)?; + println!("RETURN TYPE"); Ok(props_type) } - - fn handle_errors(props: &Vec, prop_type: &Option) -> ParseResult<()> { - let mut ref_indicator: u8 = 0; - println!("PROPS {}", props.len()); - for prop in props { - if prop.label.to_string() == "ref" { - ref_indicator = ref_indicator + 1; - if ref_indicator > 1 { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - } - match prop_type { - Some(PropType::List) => { - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - } - Some(PropType::With) => { - if ref_indicator == 0 { - return Err(syn::Error::new_spanned(&prop.label, ref_indicator)); - } - } - None => (), - } - } - - Ok(()) - } } impl PeekValue for Props { @@ -529,7 +455,16 @@ impl Parse for Props { fn parse(input: ParseStream) -> ParseResult { match Props::get_type(input)? { Some(PropType::List) => input.parse().map(|l| Props::List(Box::new(l))), - Some(PropType::With) => input.parse().map(|w| Props::With(Box::new(w))), + Some(PropType::With) => { + let result = input.parse().map(|w| Props::With(Box::new(w))); + match result { + Ok(v) => Ok(v), + Err(e) => { + println!("MY ERROR"); + return Err(input.error("MY")); + } + } + } None => Ok(Props::None), } } @@ -542,11 +477,6 @@ struct ListProps { impl Parse for ListProps { fn parse(input: ParseStream) -> ParseResult { - match Props::peek(input.cursor()) { - Some(PropType::With) => return Err(input.error(Props::collision_message())), - _ => (), - }; - let ListProps { mut props, node_ref, @@ -589,11 +519,6 @@ impl Parse for WithProps { // Check for the ref tag after `with` let mut node_ref = None; - println!( - "WITH PROPS STREAM::{}, is_some {}", - input.cursor().token_stream(), - input.cursor().ident().is_some() - ); if input.cursor().ident().is_some() { let ListProps { @@ -601,15 +526,11 @@ impl Parse for WithProps { .. } = Props::remove_refs(Props::collect_props(input)?); node_ref = reference; - println!("IS SOME {}", input.cursor().ident().is_some()); if let Some(ident) = input.cursor().ident() { let prop = input.parse::()?; - println!("WITJ IF SOME IDENT {}", ident.0); if ident.0 == "ref" { node_ref = Some(prop.value); - } else { - return Err(syn::Error::new_spanned(&prop.label, "unexpected token")); } } } diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index adf8b073355..34f2543c3e8 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -345,7 +345,7 @@ mod tests { }; html! { - + }; } } From 8a4f0678e8b46e9eccc7948e50f5c0ae2287e21e Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Tue, 3 Mar 2020 18:12:11 +0800 Subject: [PATCH 34/38] Fix with props checks --- crates/macro/src/html_tree/html_component.rs | 246 +++++++------------ tests/macro/html-component-fail.rs | 1 - tests/macro/html-component-fail.stderr | 120 +++++---- tests/macro/html-component-pass.rs | 9 +- 4 files changed, 146 insertions(+), 230 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 39a8d45e05f..9fed464395a 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -6,7 +6,6 @@ use boolinator::Boolinator; use proc_macro2::Span; use quote::{quote, quote_spanned, ToTokens}; use std::cmp::Ordering; -use std::collections::HashMap; use syn::buffer::Cursor; use syn::parse; use syn::parse::{Parse, ParseStream, Result as ParseResult}; @@ -341,17 +340,22 @@ impl ToTokens for HtmlComponentClose { } } -enum PropType { - List, - With, -} - enum Props { List(Box), With(Box), None, } +struct ListProps { + props: Vec, + node_ref: Option, +} + +struct WithProps { + props: Ident, + node_ref: Option, +} + impl Props { fn node_ref(&self) -> Option<&Expr> { match self { @@ -360,181 +364,97 @@ impl Props { Props::None => None, } } + fn collision_message() -> &'static str { "Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop" } +} - fn collect_props(input: ParseStream) -> ParseResult> { - let mut props: Vec = Vec::new(); - while HtmlProp::peek(input.cursor()).is_some() { - props.push(input.parse::()?); - } - Ok(props) - } - - fn remove_refs(mut props: Vec) -> ListProps { - let ref_position = props.iter().position(|p| p.label.to_string() == "ref"); - let node_ref = ref_position.map(|i| props.remove(i).value); - ListProps { props, node_ref } - } - - fn return_type(input: ParseStream) -> ParseResult { - let stream = input.fork(); - let mut is_with = false; - let mut ref_counter = 0; - let mut props_counter = 0; +impl Parse for Props { + fn parse(input: ParseStream) -> ParseResult { + let mut props = Props::None; + let mut node_ref: Option = None; - while let Some((token, _)) = stream.cursor().ident() { - let prop_value = stream.parse::(); + while let Some((token, _)) = input.cursor().ident() { if token == "with" { - is_with = true; - } - if is_with && (props_counter - ref_counter) > 0 { - return Err(syn::Error::new_spanned(&token, Props::collision_message())); + match props { + Props::None => Ok(()), + Props::With(_) => Err(input.error("too many `with` tokens used")), + Props::List(_) => Err(syn::Error::new_spanned(&token, Props::collision_message())), + }?; + + input.parse::()?; + props = Props::With(Box::new(WithProps { + props: input.parse::()?, + node_ref: None, + })); + + // Handle optional comma + let _ = input.parse::(); + continue; } - if let Ok(prop) = prop_value { - if prop.label.to_string() == "ref" { - ref_counter = ref_counter + 1; - if ref_counter > 1 { - return Err(syn::Error::new_spanned(&prop.label, "too many refs set")); - } - } else { - if is_with { - return Err(syn::Error::new_spanned(&token, Props::collision_message())); - } - } - if prop.label.to_string() == "type" { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - if !prop.label.extended.is_empty() { - return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); - } - props_counter = props_counter + 1; - } - } - if is_with { - Ok(PropType::With) - } else { - Ok(PropType::List) - } - } - - fn get_type(input: ParseStream) -> ParseResult> { - let props_type = match Props::return_type(input) { - Ok(props) => Some(props), - Err(_) => None, - }; - - match props_type { - Some(PropType::With) => println!("props_type::with"), - Some(PropType::List) => println!("props_type::list"), - None => println!("none"), - } - let _ = Props::collect_props(input)?; - - println!("RETURN TYPE"); - Ok(props_type) - } -} - -impl PeekValue for Props { - fn peek(cursor: Cursor) -> Option { - let (ident, _) = cursor.ident()?; - let prop_type = if ident == "with" { - PropType::With - } else { - PropType::List - }; - - Some(prop_type) - } -} - -impl Parse for Props { - fn parse(input: ParseStream) -> ParseResult { - match Props::get_type(input)? { - Some(PropType::List) => input.parse().map(|l| Props::List(Box::new(l))), - Some(PropType::With) => { - let result = input.parse().map(|w| Props::With(Box::new(w))); - match result { - Ok(v) => Ok(v), - Err(e) => { - println!("MY ERROR"); - return Err(input.error("MY")); - } - } + if (HtmlProp::peek(input.cursor())).is_none() { + break; } - None => Ok(Props::None), - } - } -} -struct ListProps { - props: Vec, - node_ref: Option, -} + let prop = input.parse::()?; + if prop.label.to_string() == "ref" { + match node_ref { + None => Ok(()), + Some(_) => Err(syn::Error::new_spanned(&prop.label, "too many refs set")), + }?; -impl Parse for ListProps { - fn parse(input: ParseStream) -> ParseResult { - let ListProps { - mut props, - node_ref, - } = Props::remove_refs(Props::collect_props(input)?); - - // alphabetize - props.sort_by(|a, b| { - if a.label == b.label { - Ordering::Equal - } else if a.label.to_string() == "children" { - Ordering::Greater - } else if b.label.to_string() == "children" { - Ordering::Less - } else { - a.label - .to_string() - .partial_cmp(&b.label.to_string()) - .unwrap() + node_ref = Some(prop.value); + continue; } - }); - Ok(ListProps { props, node_ref }) - } -} + if prop.label.to_string() == "type" { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } -struct WithProps { - props: Ident, - node_ref: Option, -} + if !prop.label.extended.is_empty() { + return Err(syn::Error::new_spanned(&prop.label, "expected identifier")); + } -impl Parse for WithProps { - fn parse(input: ParseStream) -> ParseResult { - let with = input.parse::()?; - if with != "with" { - return Err(input.error("expected to find `with` token")); + match props { + ref mut props @ Props::None => { + *props = Props::List(Box::new(ListProps { + props: vec![prop], + node_ref: None, + })); + }, + Props::With(_) => return Err(syn::Error::new_spanned(&token, Props::collision_message())), + Props::List(ref mut list) => { + list.props.push(prop); + } + }; } - let props = input.parse::()?; - - let _ = input.parse::(); - - // Check for the ref tag after `with` - let mut node_ref = None; - if input.cursor().ident().is_some() { - let ListProps { - node_ref: reference, - .. - } = Props::remove_refs(Props::collect_props(input)?); - node_ref = reference; - - if let Some(ident) = input.cursor().ident() { - let prop = input.parse::()?; - if ident.0 == "ref" { - node_ref = Some(prop.value); - } + match props { + Props::None => {}, + Props::With(ref mut p) => p.node_ref = node_ref, + Props::List(ref mut p) => { + p.node_ref = node_ref; + + // alphabetize + p.props.sort_by(|a, b| { + if a.label == b.label { + Ordering::Equal + } else if a.label.to_string() == "children" { + Ordering::Greater + } else if b.label.to_string() == "children" { + Ordering::Less + } else { + a.label + .to_string() + .partial_cmp(&b.label.to_string()) + .unwrap() + } + }); } - } + }; - Ok(WithProps { props, node_ref }) + Ok(props) } } diff --git a/tests/macro/html-component-fail.rs b/tests/macro/html-component-fail.rs index dc2a14833d1..a19fbd14b6f 100644 --- a/tests/macro/html-component-fail.rs +++ b/tests/macro/html-component-fail.rs @@ -62,7 +62,6 @@ fn compile_fail() { html! { }; html! { }; html! { }; - html! { }; html! { }; html! { }; html! { }; diff --git a/tests/macro/html-component-fail.stderr b/tests/macro/html-component-fail.stderr index f041677fc9f..68cfc1c9048 100644 --- a/tests/macro/html-component-fail.stderr +++ b/tests/macro/html-component-fail.stderr @@ -66,119 +66,113 @@ error: Using special syntax `with props` along with named prop is not allowed. T 63 | html! { }; | ^^^^ -error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:64:43 +error: too many refs set + --> $DIR/html-component-fail.rs:64:27 | 64 | html! { }; - | ^^^^ - -error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:65:27 - | -65 | html! { }; - | ^^^^ + | ^^^ error: unexpected token - --> $DIR/html-component-fail.rs:67:31 + --> $DIR/html-component-fail.rs:66:31 | -67 | html! { }; +66 | html! { }; | ^^ error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:68:28 + --> $DIR/html-component-fail.rs:67:28 | -68 | html! { }; +67 | html! { }; | ^^^^ error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:69:31 + --> $DIR/html-component-fail.rs:68:31 | -69 | html! { }; +68 | html! { }; | ^^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:70:20 + --> $DIR/html-component-fail.rs:69:20 | -70 | html! { }; +69 | html! { }; | ^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:71:20 + --> $DIR/html-component-fail.rs:70:20 | -71 | html! { }; +70 | html! { }; | ^^^^^^^^^^^^^^^^^ error: unexpected end of input, expected expression - --> $DIR/html-component-fail.rs:73:5 + --> $DIR/html-component-fail.rs:72:5 | -73 | html! { }; +72 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: too many refs set - --> $DIR/html-component-fail.rs:78:33 + --> $DIR/html-component-fail.rs:77:33 | -78 | html! { }; +77 | html! { }; | ^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:81:13 + --> $DIR/html-component-fail.rs:80:13 | -81 | html! { }; +80 | html! { }; | ^^^^^^^^ error: this open tag has no corresponding close tag - --> $DIR/html-component-fail.rs:82:13 + --> $DIR/html-component-fail.rs:81:13 | -82 | html! { }; +81 | html! { }; | ^^^^^^^ error: only one root html element allowed - --> $DIR/html-component-fail.rs:83:28 + --> $DIR/html-component-fail.rs:82:28 | -83 | html! { }; +82 | html! { }; | ^^^^^^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:92:30 + --> $DIR/html-component-fail.rs:91:30 | -92 | html! { > }; +91 | html! { > }; | ^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:93:30 + --> $DIR/html-component-fail.rs:92:30 | -93 | html! { >>> }; +92 | html! { >>> }; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `blah` in this scope - --> $DIR/html-component-fail.rs:66:25 + --> $DIR/html-component-fail.rs:65:25 | -66 | html! { }; +65 | html! { }; | ^^^^ not found in this scope error[E0609]: no field `unknown` on type `ChildProperties` - --> $DIR/html-component-fail.rs:72:20 + --> $DIR/html-component-fail.rs:71:20 | -72 | html! { }; +71 | html! { }; | ^^^^^^^ unknown field | = note: available fields are: `string`, `int` error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:72:20 + --> $DIR/html-component-fail.rs:71:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `unknown` not found for this ... -72 | html! { }; +71 | html! { }; | ^^^^^^^ method not found in `ChildPropertiesBuilder` 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:74:33 + --> $DIR/html-component-fail.rs:73:33 | -74 | html! { }; +73 | html! { }; | ^^ the trait `yew::virtual_dom::Transformer<(), std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -190,9 +184,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:75:33 + --> $DIR/html-component-fail.rs:74:33 | -75 | html! { }; +74 | html! { }; | ^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -204,9 +198,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:76:33 + --> $DIR/html-component-fail.rs:75:33 | -76 | html! { }; +75 | html! { }; | ^^^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -218,15 +212,15 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0308]: mismatched types - --> $DIR/html-component-fail.rs:77:30 + --> $DIR/html-component-fail.rs:76:30 | -77 | html! { }; +76 | html! { }; | ^^ expected struct `yew::html::NodeRef`, found `()` error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer` is not satisfied - --> $DIR/html-component-fail.rs:79:24 + --> $DIR/html-component-fail.rs:78:24 | -79 | html! { }; +78 | html! { }; | ^^^^ the trait `yew::virtual_dom::Transformer` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -238,51 +232,51 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:80:20 + --> $DIR/html-component-fail.rs:79:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `string` not found for this ... -80 | html! { }; +79 | html! { }; | ^^^^^^ method not found in `ChildPropertiesBuilder` error[E0599]: no method named `children` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:84:5 + --> $DIR/html-component-fail.rs:83:5 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `children` not found for this ... -84 | html! { { "Not allowed" } }; +83 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:86:5 + --> $DIR/html-component-fail.rs:85:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -86 | html! { }; +85 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:87:5 + --> $DIR/html-component-fail.rs:86:5 | 23 | #[derive(Clone, Properties)] | ---------- method `build` not found for this ... -87 | html! { }; +86 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From<&str>` is not satisfied - --> $DIR/html-component-fail.rs:88:5 + --> $DIR/html-component-fail.rs:87:5 | -88 | html! { { "Not allowed" } }; +87 | html! { { "Not allowed" } }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `&str` @@ -290,9 +284,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:89:5 + --> $DIR/html-component-fail.rs:88:5 | -89 | html! { <> }; +88 | html! { <> }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` @@ -300,9 +294,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::conv = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:90:5 + --> $DIR/html-component-fail.rs:89:5 | -90 | html! { }; +89 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` | = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` diff --git a/tests/macro/html-component-pass.rs b/tests/macro/html-component-pass.rs index 68283badd52..53189e49727 100644 --- a/tests/macro/html-component-pass.rs +++ b/tests/macro/html-component-pass.rs @@ -178,12 +178,15 @@ fn compile_pass() { let props = ::Properties::default(); let props2 = ::Properties::default(); + let props3 = ::Properties::default(); + let props4 = ::Properties::default(); + let node_ref = NodeRef::default(); html! { <> - - // backwards compat - + // backwards compat + + }; From 748c62d25a5e2f3a9f55d1973beeb6af3bbda366 Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 4 Mar 2020 20:07:22 +0100 Subject: [PATCH 35/38] remove comments --- src/virtual_dom/vcomp.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index 304b613b0cd..29f9d407e37 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -350,21 +350,21 @@ mod tests { #[test] fn set_properties_to_component() { - // html! { - // - // }; + html! { + + }; - // html! { - // - // }; + html! { + + }; - // html! { - // - // }; + html! { + + }; - // html! { - // - // }; + html! { + + }; let props = Props { field_1: 1, From b8c8a3857c7a719590693e1adf515f381b09b94e Mon Sep 17 00:00:00 2001 From: Serhii Date: Wed, 4 Mar 2020 20:08:01 +0100 Subject: [PATCH 36/38] update --- src/virtual_dom/vcomp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/virtual_dom/vcomp.rs b/src/virtual_dom/vcomp.rs index 29f9d407e37..8d60b5e3ef3 100644 --- a/src/virtual_dom/vcomp.rs +++ b/src/virtual_dom/vcomp.rs @@ -372,7 +372,7 @@ mod tests { }; html! { - + }; } } From 5b64ce8fae5daca3b417e2758d96331797add56c Mon Sep 17 00:00:00 2001 From: Serhii Date: Thu, 5 Mar 2020 18:42:00 +0100 Subject: [PATCH 37/38] format --- crates/macro/src/html_tree/html_component.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/macro/src/html_tree/html_component.rs b/crates/macro/src/html_tree/html_component.rs index 782232daace..56b4820b33c 100644 --- a/crates/macro/src/html_tree/html_component.rs +++ b/crates/macro/src/html_tree/html_component.rs @@ -380,7 +380,9 @@ impl Parse for Props { match props { Props::None => Ok(()), Props::With(_) => Err(input.error("too many `with` tokens used")), - Props::List(_) => Err(syn::Error::new_spanned(&token, Props::collision_message())), + Props::List(_) => { + Err(syn::Error::new_spanned(&token, Props::collision_message())) + } }?; input.parse::()?; @@ -423,8 +425,10 @@ impl Parse for Props { props: vec![prop], node_ref: None, })); - }, - Props::With(_) => return Err(syn::Error::new_spanned(&token, Props::collision_message())), + } + Props::With(_) => { + return Err(syn::Error::new_spanned(&token, Props::collision_message())) + } Props::List(ref mut list) => { list.props.push(prop); } @@ -432,7 +436,7 @@ impl Parse for Props { } match props { - Props::None => {}, + Props::None => {} Props::With(ref mut p) => p.node_ref = node_ref, Props::List(ref mut p) => { p.node_ref = node_ref; From 7fd238226d6fa28a078b981d88ede6dec94255b9 Mon Sep 17 00:00:00 2001 From: Justin Starry Date: Fri, 6 Mar 2020 06:58:49 +0800 Subject: [PATCH 38/38] Fix test --- .../tests/macro/html-component-fail.stderr | 232 ++++++++++-------- 1 file changed, 131 insertions(+), 101 deletions(-) diff --git a/crates/macro/tests/macro/html-component-fail.stderr b/crates/macro/tests/macro/html-component-fail.stderr index 2c44be42848..82de6abf39d 100644 --- a/crates/macro/tests/macro/html-component-fail.stderr +++ b/crates/macro/tests/macro/html-component-fail.stderr @@ -30,119 +30,149 @@ error: this open tag has no corresponding close tag 74 | html! { }; | ^^^^^^^^^^^^^^^^^^^ -error: unexpected token +error: too many refs set --> $DIR/html-component-fail.rs:75:38 | 75 | html! { }; | ^^^ -error: unexpected token - --> $DIR/html-component-fail.rs:76:27 +error: too many refs set + --> $DIR/html-component-fail.rs:76:38 | -76 | html! { }; - | ^^^^ +76 | html! { }; + | ^^^ -error: unexpected token +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:77:38 + | +77 | html! { }; + | ^^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop --> $DIR/html-component-fail.rs:78:31 | -78 | html! { }; +78 | html! { }; + | ^^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:79:28 + | +79 | html! { }; + | ^^^^ + +error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop + --> $DIR/html-component-fail.rs:80:35 + | +80 | html! { }; + | ^^^^ + +error: too many refs set + --> $DIR/html-component-fail.rs:81:27 + | +81 | html! { }; + | ^^^ + +error: unexpected token + --> $DIR/html-component-fail.rs:83:31 + | +83 | html! { }; | ^^ error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:67:28 + --> $DIR/html-component-fail.rs:84:28 | -67 | html! { }; +84 | html! { }; | ^^^^ error: Using special syntax `with props` along with named prop is not allowed. This rule does not apply to special `ref` prop - --> $DIR/html-component-fail.rs:68:31 + --> $DIR/html-component-fail.rs:85:31 | -68 | html! { }; +85 | html! { }; | ^^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:79:20 + --> $DIR/html-component-fail.rs:86:20 | -79 | html! { }; +86 | html! { }; | ^^^^ error: expected identifier - --> $DIR/html-component-fail.rs:80:20 + --> $DIR/html-component-fail.rs:87:20 | -80 | html! { }; +87 | html! { }; | ^^^^^^^^^^^^^^^^^ error: unexpected end of input, expected expression - --> $DIR/html-component-fail.rs:82:5 + --> $DIR/html-component-fail.rs:89:5 | -82 | html! { }; +89 | html! { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: too many refs set - --> $DIR/html-component-fail.rs:87:33 + --> $DIR/html-component-fail.rs:94:33 | -87 | html! { }; +94 | html! { }; | ^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:90:13 + --> $DIR/html-component-fail.rs:97:13 | -90 | html! { }; +97 | html! { }; | ^^^^^^^^ error: this open tag has no corresponding close tag - --> $DIR/html-component-fail.rs:91:13 + --> $DIR/html-component-fail.rs:98:13 | -91 | html! { }; +98 | html! { }; | ^^^^^^^ error: only one root html element allowed - --> $DIR/html-component-fail.rs:92:28 + --> $DIR/html-component-fail.rs:99:28 | -92 | html! { }; +99 | html! { }; | ^^^^^^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:101:30 + --> $DIR/html-component-fail.rs:108:30 | -101 | html! { > }; +108 | html! { > }; | ^^^^^^^^^^ error: this close tag has no corresponding open tag - --> $DIR/html-component-fail.rs:102:30 + --> $DIR/html-component-fail.rs:109:30 | -102 | html! { >>> }; +109 | html! { >>> }; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find value `blah` in this scope - --> $DIR/html-component-fail.rs:77:25 + --> $DIR/html-component-fail.rs:82:25 | -77 | html! { }; +82 | html! { }; | ^^^^ not found in this scope error[E0609]: no field `unknown` on type `ChildProperties` - --> $DIR/html-component-fail.rs:81:20 + --> $DIR/html-component-fail.rs:88:20 | -81 | html! { }; +88 | html! { }; | ^^^^^^^ unknown field | = note: available fields are: `string`, `int` error[E0599]: no method named `unknown` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:81:20 + --> $DIR/html-component-fail.rs:88:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `unknown` not found for this ... -81 | html! { }; +88 | html! { }; | ^^^^^^^ method not found in `ChildPropertiesBuilder` 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:83:33 + --> $DIR/html-component-fail.rs:90:33 | -83 | html! { }; +90 | html! { }; | ^^ the trait `yew::virtual_dom::Transformer<(), std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -154,9 +184,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:84:33 + --> $DIR/html-component-fail.rs:91:33 | -84 | html! { }; +91 | html! { }; | ^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -168,9 +198,9 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` 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:85:33 + --> $DIR/html-component-fail.rs:92:33 | -85 | html! { }; +92 | html! { }; | ^^^ the trait `yew::virtual_dom::Transformer<{integer}, std::string::String>` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -182,15 +212,15 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0308]: mismatched types - --> $DIR/html-component-fail.rs:86:30 + --> $DIR/html-component-fail.rs:93:30 | -86 | html! { }; +93 | html! { }; | ^^ expected struct `yew::html::NodeRef`, found `()` error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom::Transformer` is not satisfied - --> $DIR/html-component-fail.rs:88:24 + --> $DIR/html-component-fail.rs:95:24 | -88 | html! { }; +95 | html! { }; | ^^^^ the trait `yew::virtual_dom::Transformer` is not implemented for `yew::virtual_dom::vcomp::VComp` | = help: the following implementations were found: @@ -202,12 +232,12 @@ error[E0277]: the trait bound `yew::virtual_dom::vcomp::VComp: yew::virtual_dom: = note: required by `yew::virtual_dom::Transformer::transform` error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:89:20 + --> $DIR/html-component-fail.rs:96:20 | 6 | #[derive(Clone, Properties, PartialEq)] | ---------- method `string` not found for this ... -89 | html! { }; +96 | html! { }; | ^^^^^^ method not found in `ChildPropertiesBuilder` | = help: items from traits can only be used if the trait is implemented and in scope @@ -215,70 +245,70 @@ error[E0599]: no method named `string` found for type `ChildPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:93:5 - | -6 | #[derive(Clone, Properties, PartialEq)] - | ---------- method `children` not found for this + --> $DIR/html-component-fail.rs:100:5 + | +6 | #[derive(Clone, Properties, PartialEq)] + | ---------- method `children` not found for this ... -93 | html! { { "Not allowed" } }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` - | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +100 | html! { { "Not allowed" } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildPropertiesBuilder` + | + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:95:5 - | -29 | #[derive(Clone, Properties)] - | ---------- method `build` not found for this + --> $DIR/html-component-fail.rs:102:5 + | +29 | #[derive(Clone, Properties)] + | ---------- method `build` not found for this ... -95 | html! { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` - | - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `build`, perhaps you need to implement it: - candidate #1: `proc_macro::bridge::server::TokenStreamBuilder` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +102 | html! { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `build`, perhaps you need to implement it: + candidate #1: `proc_macro::bridge::server::TokenStreamBuilder` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0599]: no method named `build` found for type `ChildContainerPropertiesBuilder` in the current scope - --> $DIR/html-component-fail.rs:96:5 - | -29 | #[derive(Clone, Properties)] - | ---------- method `build` not found for this + --> $DIR/html-component-fail.rs:103:5 + | +29 | #[derive(Clone, Properties)] + | ---------- method `build` not found for this ... -96 | html! { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` - | - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `build`, perhaps you need to implement it: - candidate #1: `proc_macro::bridge::server::TokenStreamBuilder` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) +103 | html! { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `ChildContainerPropertiesBuilder` + | + = help: items from traits can only be used if the trait is implemented and in scope + = note: the following trait defines an item `build`, perhaps you need to implement it: + candidate #1: `proc_macro::bridge::server::TokenStreamBuilder` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From<&str>` is not satisfied - --> $DIR/html-component-fail.rs:97:5 - | -97 | html! { { "Not allowed" } }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `yew::virtual_dom::vcomp::VChild` - | - = note: required because of the requirements on the impl of `std::convert::Into>` for `&str` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq<&str, yew::virtual_dom::vcomp::VChild>` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/html-component-fail.rs:104:5 + | +104 | html! { { "Not allowed" } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&str>` is not implemented for `yew::virtual_dom::vcomp::VChild` + | + = note: required because of the requirements on the impl of `std::convert::Into>` for `&str` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq<&str, yew::virtual_dom::vcomp::VChild>` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:98:5 - | -98 | html! { <> }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` - | - = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq>` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/html-component-fail.rs:105:5 + | +105 | html! { <> }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` + | + = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq>` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error[E0277]: the trait bound `yew::virtual_dom::vcomp::VChild: std::convert::From` is not satisfied - --> $DIR/html-component-fail.rs:99:5 - | -99 | html! { }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` - | - = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` - = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq>` - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + --> $DIR/html-component-fail.rs:106:5 + | +106 | html! { }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `yew::virtual_dom::vcomp::VChild` + | + = note: required because of the requirements on the impl of `std::convert::Into>` for `yew::virtual_dom::vnode::VNode` + = note: required because of the requirements on the impl of `std::iter::IntoIterator` for `yew::utils::NodeSeq>` + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)