From a9038daeeab72406e13e16e9760c9c027fa935fa Mon Sep 17 00:00:00 2001 From: Muhammad Hamza Date: Sun, 25 Sep 2022 22:00:38 +0500 Subject: [PATCH] Fix issues with tuples in closing tag --- .../yew-macro/src/html_tree/html_component.rs | 161 ++---------------- .../html_macro/generic-component-fail.stderr | 22 ++- .../html_macro/generic-component-pass.rs | 1 + 3 files changed, 26 insertions(+), 158 deletions(-) diff --git a/packages/yew-macro/src/html_tree/html_component.rs b/packages/yew-macro/src/html_tree/html_component.rs index 1a13b16351d..9f8dd962cb8 100644 --- a/packages/yew-macro/src/html_tree/html_component.rs +++ b/packages/yew-macro/src/html_tree/html_component.rs @@ -1,18 +1,11 @@ -use boolinator::Boolinator; use proc_macro2::Span; use quote::{quote, quote_spanned, ToTokens}; -use syn::buffer::Cursor; use syn::parse::{Parse, ParseStream}; -use syn::punctuated::Punctuated; use syn::spanned::Spanned; -use syn::{ - AngleBracketedGenericArguments, GenericArgument, Path, PathArguments, PathSegment, Token, Type, - TypePath, -}; +use syn::{Token, Type}; use super::{HtmlChildrenTree, TagTokens}; use crate::props::ComponentProps; -use crate::PeekValue; pub struct HtmlComponent { ty: Type, @@ -21,17 +14,16 @@ pub struct HtmlComponent { close: Option, } -impl PeekValue<()> for HtmlComponent { - fn peek(cursor: Cursor) -> Option<()> { - HtmlComponentOpen::peek(cursor) - .or_else(|| HtmlComponentClose::peek(cursor)) - .map(|_| ()) - } -} - impl Parse for HtmlComponent { fn parse(input: ParseStream) -> syn::Result { - if HtmlComponentClose::peek(input.cursor()).is_some() { + // check if the next tokens are () { Ok(close) => Err(syn::Error::new_spanned( close.to_spanned(), @@ -60,12 +52,10 @@ impl Parse for HtmlComponent { "this opening tag has no corresponding closing tag", )); } - if let Some(ty) = HtmlComponentClose::peek(input.cursor()) { - if open.ty == ty { - break; - } - } + if trying_to_close() { + break; + } children.parse_child(input)?; } @@ -127,108 +117,6 @@ impl ToTokens for HtmlComponent { } } -impl HtmlComponent { - fn double_colon(mut cursor: Cursor) -> Option { - for _ in 0..2 { - let (punct, c) = cursor.punct()?; - (punct.as_char() == ':').as_option()?; - cursor = c; - } - - Some(cursor) - } - - /// Refer to the [`syn::parse::Parse`] implementation for [`AngleBracketedGenericArguments`]. - fn path_arguments(mut cursor: Cursor) -> Option<(PathArguments, Cursor)> { - let (punct, c) = cursor.punct()?; - cursor = c; - (punct.as_char() == '<').as_option()?; - - let mut args = Punctuated::new(); - - loop { - let punct = cursor.punct(); - if let Some((punct, c)) = punct { - if punct.as_char() == '>' { - cursor = c; - break; - } - } - - let (ty, c) = Self::peek_type(cursor); - cursor = c; - - args.push_value(GenericArgument::Type(ty)); - - let punct = cursor.punct(); - if let Some((punct, c)) = punct { - cursor = c; - if punct.as_char() == '>' { - break; - } else if punct.as_char() == ',' { - args.push_punct(Token![,](Span::mixed_site())) - } - } - } - - Some(( - PathArguments::AngleBracketed(AngleBracketedGenericArguments { - colon2_token: None, - lt_token: Token![<](Span::mixed_site()), - args, - gt_token: Token![>](Span::mixed_site()), - }), - cursor, - )) - } - - fn peek_type(mut cursor: Cursor) -> (Type, Cursor) { - let mut colons_optional = true; - let mut leading_colon = None; - let mut segments = Punctuated::new(); - - loop { - let mut post_colons_cursor = cursor; - if let Some(c) = Self::double_colon(post_colons_cursor) { - if colons_optional { - leading_colon = Some(Token![::](Span::mixed_site())); - } - post_colons_cursor = c; - } else if !colons_optional { - break; - } - - if let Some((ident, c)) = post_colons_cursor.ident() { - cursor = c; - let arguments = if let Some((args, c)) = Self::path_arguments(cursor) { - cursor = c; - args - } else { - PathArguments::None - }; - - segments.push(PathSegment { ident, arguments }); - } else { - break; - } - - // only first `::` is optional - colons_optional = false; - } - - ( - Type::Path(TypePath { - qself: None, - path: Path { - leading_colon, - segments, - }, - }), - cursor, - ) - } -} - struct HtmlComponentOpen { tag: TagTokens, ty: Type, @@ -244,15 +132,6 @@ impl HtmlComponentOpen { } } -impl PeekValue for HtmlComponentOpen { - fn peek(cursor: Cursor) -> Option { - let (punct, cursor) = cursor.punct()?; - (punct.as_char() == '<').as_option()?; - let (typ, _) = HtmlComponent::peek_type(cursor); - Some(typ) - } -} - impl Parse for HtmlComponentOpen { fn parse(input: ParseStream) -> syn::Result { TagTokens::parse_start_content(input, |input, tag| { @@ -282,22 +161,6 @@ impl HtmlComponentClose { } } -impl PeekValue for HtmlComponentClose { - fn peek(cursor: Cursor) -> Option { - let (punct, cursor) = cursor.punct()?; - (punct.as_char() == '<').as_option()?; - - let (punct, cursor) = cursor.punct()?; - (punct.as_char() == '/').as_option()?; - - let (typ, cursor) = HtmlComponent::peek_type(cursor); - - let (punct, _) = cursor.punct()?; - (punct.as_char() == '>').as_option()?; - - Some(typ) - } -} impl Parse for HtmlComponentClose { fn parse(input: ParseStream) -> syn::Result { TagTokens::parse_end_content(input, |input, tag| { diff --git a/packages/yew-macro/tests/html_macro/generic-component-fail.stderr b/packages/yew-macro/tests/html_macro/generic-component-fail.stderr index 33312601115..7ce8f5a802d 100644 --- a/packages/yew-macro/tests/html_macro/generic-component-fail.stderr +++ b/packages/yew-macro/tests/html_macro/generic-component-fail.stderr @@ -1,17 +1,21 @@ error: this opening tag has no corresponding closing tag - --> $DIR/generic-component-fail.rs:43:13 + --> tests/html_macro/generic-component-fail.rs:43:13 | 43 | html! { > }; | ^^^^^^^^^^^^^^^^^ -error: this closing tag has no corresponding opening tag - --> $DIR/generic-component-fail.rs:44:30 +error[E0107]: missing generics for struct `Generic` + --> tests/html_macro/generic-component-fail.rs:44:32 | 44 | html! { > }; - | ^^^^^^^^^^ - -error: this closing tag has no corresponding opening tag - --> $DIR/generic-component-fail.rs:45:30 + | ^^^^^^^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `T` + --> tests/html_macro/generic-component-fail.rs:4:12 + | +4 | pub struct Generic { + | ^^^^^^^ - +help: add missing generic argument | -45 | html! { >>> }; - | ^^^^^^^^^^^^^^^^^^^^^^^ +44 | html! { >> }; + | ~~~~~~~~~~ diff --git a/packages/yew-macro/tests/html_macro/generic-component-pass.rs b/packages/yew-macro/tests/html_macro/generic-component-pass.rs index e520923e473..4aca8a05457 100644 --- a/packages/yew-macro/tests/html_macro/generic-component-pass.rs +++ b/packages/yew-macro/tests/html_macro/generic-component-pass.rs @@ -78,6 +78,7 @@ where fn compile_pass() { ::yew::html! { /> }; ::yew::html! { /> }; + ::yew::html! { >> }; ::yew::html! { >> }; ::yew::html! { > /> };