Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with tuples in closing tag #2886

Merged
merged 5 commits into from Oct 8, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
45 changes: 40 additions & 5 deletions packages/yew-macro/src/html_tree/html_component.rs
@@ -1,5 +1,6 @@
use proc_macro2::Span;
use quote::{quote, quote_spanned, ToTokens};
use syn::parse::discouraged::Speculative;
use syn::parse::{Parse, ParseStream};
use syn::spanned::Spanned;
use syn::{Token, Type};
Expand Down Expand Up @@ -45,7 +46,7 @@ impl Parse for HtmlComponent {
}

let mut children = HtmlChildrenTree::new();
loop {
let close = loop {
if input.is_empty() {
return Err(syn::Error::new_spanned(
open.to_spanned(),
Expand All @@ -54,12 +55,46 @@ impl Parse for HtmlComponent {
}

if trying_to_close() {
break;
let cursor = input.cursor();
let _ = cursor
.punct()
.and_then(|(_, cursor)| cursor.punct())
.and_then(|(_, cursor)| cursor.ident())
.ok_or_else(|| {
syn::Error::new(Span::call_site(), "expected a valid closing tag (e.g.: </Component>)")
})?;

let fork = input.fork();
hamza1311 marked this conversation as resolved.
Show resolved Hide resolved
let lt = fork.parse::<Token![<]>()?;
let div = Some(fork.parse::<Token![/]>()?);
let ty = fork.parse::<Type>()?;
if ty != open.ty {
fn format_token_stream(ts: impl ToTokens) -> String {
let string = ts.to_token_stream().to_string();
// remove unnecessary spaces
string.replace(' ', "")
}
let open_ty = open.ty;
return Err(syn::Error::new_spanned(
quote!(#open_ty #ty),
format!(
"mismatched closing tags: expected `{}`, found `{}`",
format_token_stream(open_ty),
format_token_stream(ty)
),
));
} else {
let gt = fork.parse::<Token![>]>()?;
let close = HtmlComponentClose {
tag: TagTokens { lt, div, gt },
ty,
};
input.advance_to(&fork);
break close;
}
}
children.parse_child(input)?;
}

let close = input.parse::<HtmlComponentClose>()?;
};

if !children.is_empty() {
if let Some(children_prop) = open.props.children() {
Expand Down
30 changes: 30 additions & 0 deletions packages/yew-macro/tests/html_macro/component-fail.rs
Expand Up @@ -148,4 +148,34 @@ fn not_expressions() {
html! { <HtmlInProps header={format!("ending with semi");} /> };
}

fn mismatch_closing_tags() {
pub struct A;
impl Component for A {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
unimplemented!()
}
fn view(&self, _ctx: &Context<Self>) -> Html {
unimplemented!()
}
}

pub struct B;
impl Component for B {
type Message = ();
type Properties = ();

fn create(_ctx: &Context<Self>) -> Self {
unimplemented!()
}
fn view(&self, _ctx: &Context<Self>) -> Html {
unimplemented!()
}
}
let _ = html! { <A></B> };
let _ = html! { <A></> };
}

fn main() {}
14 changes: 14 additions & 0 deletions packages/yew-macro/tests/html_macro/component-fail.stderr
Expand Up @@ -386,6 +386,20 @@ error: only an expression may be assigned as a property. Consider removing this
148 | html! { <HtmlInProps header={format!("ending with semi");} /> };
| ^

error: mismatched closing tags: expected `A`, found `B`
--> tests/html_macro/component-fail.rs:177:22
|
177 | let _ = html! { <A></B> };
| ^^^^^

error: expected a valid closing tag (e.g.: </Component>)
--> tests/html_macro/component-fail.rs:178:13
|
178 | let _ = html! { <A></> };
| ^^^^^^^^^^^^^^^^
hamza1311 marked this conversation as resolved.
Show resolved Hide resolved
|
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0425]: cannot find value `blah` in this scope
--> tests/html_macro/component-fail.rs:82:22
|
Expand Down
6 changes: 6 additions & 0 deletions packages/yew-macro/tests/html_macro/generic-component-fail.rs
Expand Up @@ -40,9 +40,15 @@ where
}}

fn compile_fail() {
#[allow(unused_imports)]
use std::path::Path;

html! { <Generic<String>> };
html! { <Generic<String>></Generic> };
html! { <Generic<String>></Generic<Vec<String>>> };

html! { <Generic<String>></Generic<Path>> };
html! { <Generic<String>></> };
}

fn main() {}
36 changes: 23 additions & 13 deletions packages/yew-macro/tests/html_macro/generic-component-fail.stderr
@@ -1,21 +1,31 @@
error: this opening tag has no corresponding closing tag
--> tests/html_macro/generic-component-fail.rs:43:13
--> tests/html_macro/generic-component-fail.rs:46:13
|
43 | html! { <Generic<String>> };
46 | html! { <Generic<String>> };
| ^^^^^^^^^^^^^^^^^

error[E0107]: missing generics for struct `Generic`
--> tests/html_macro/generic-component-fail.rs:44:32
error: mismatched closing tags: expected `Generic<String>`, found `Generic`
--> tests/html_macro/generic-component-fail.rs:47:14
|
44 | html! { <Generic<String>></Generic> };
| ^^^^^^^ expected 1 generic argument
47 | html! { <Generic<String>></Generic> };
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: mismatched closing tags: expected `Generic<String>`, found `Generic<Vec<String>>`
--> tests/html_macro/generic-component-fail.rs:48:14
|
48 | html! { <Generic<String>></Generic<Vec<String>>> };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: mismatched closing tags: expected `Generic<String>`, found `Generic<Path>`
--> tests/html_macro/generic-component-fail.rs:50:14
|
note: struct defined here, with 1 generic parameter: `T`
--> tests/html_macro/generic-component-fail.rs:4:12
50 | html! { <Generic<String>></Generic<Path>> };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: expected a valid closing tag (e.g.: </Component>)
--> tests/html_macro/generic-component-fail.rs:51:5
|
4 | pub struct Generic<T> {
| ^^^^^^^ -
help: add missing generic argument
51 | html! { <Generic<String>></> };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
44 | html! { <Generic<String>></Generic<T>> };
| ~~~~~~~~~~
= note: this error originates in the macro `html` (in Nightly builds, run with -Z macro-backtrace for more info)