Fix parsing of braced expressions followed by a method (#4035)
* Fix parsing of braced expressions followed by a method * Improves the logic for parsing braced expressions * Fix hot-reload issue * Added cases for braced expressions followed by identifiers or string literals
This commit is contained in:
1 parent
f43a8c69fa
commit
71d85e6dd5
2 files changed
+53
-3
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::{Delimiter, TokenStream as TokenStream2, TokenTree};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use std::hash;
|
use std::hash;
|
||||||
use syn::{parse::Parse, spanned::Spanned, token::Brace, Expr};
|
use syn::{parse::Parse, spanned::Spanned, token::Brace, Expr};
|
||||||
@@ -15,8 +15,33 @@ pub struct PartialExpr {
|
|||||||
|
|
||||||
impl Parse for PartialExpr {
|
impl Parse for PartialExpr {
|
||||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||||
// Parse as an expression if there is no brace
|
// Input is a braced expression if it's a braced group
|
||||||
if !input.peek(syn::token::Brace) {
|
// followed by either of the following:
|
||||||
|
// - the end of the stream
|
||||||
|
// - a comma
|
||||||
|
// - another braced group
|
||||||
|
// - an identifier
|
||||||
|
// - a string literal
|
||||||
|
let mut is_braced = false;
|
||||||
|
if let Some((TokenTree::Group(group), next)) = input.fork().cursor().token_tree() {
|
||||||
|
let next_char_is_a_comma = next.punct().is_some_and(|(tt, _)| tt.as_char() == ',');
|
||||||
|
let next_is_a_braced_exp = next.group(Delimiter::Brace).is_some();
|
||||||
|
let next_is_an_ident = next.ident().is_some();
|
||||||
|
let next_is_a_string_literal = next.literal().is_some();
|
||||||
|
|
||||||
|
if group.delimiter() == Delimiter::Brace
|
||||||
|
&& (next.eof()
|
||||||
|
|| next_char_is_a_comma
|
||||||
|
|| next_is_a_braced_exp
|
||||||
|
|| next_is_an_ident
|
||||||
|
|| next_is_a_string_literal)
|
||||||
|
{
|
||||||
|
is_braced = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse as an expression if it's not braced
|
||||||
|
if !is_braced {
|
||||||
let expr = input.parse::<syn::Expr>()?;
|
let expr = input.parse::<syn::Expr>()?;
|
||||||
return Ok(Self {
|
return Ok(Self {
|
||||||
brace: None,
|
brace: None,
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ fn complex_kitchen_sink() {
|
|||||||
// complex_carry
|
// complex_carry
|
||||||
button {
|
button {
|
||||||
class: "flex items-center pl-3 py-3 pr-2 text-gray-500 hover:bg-indigo-50 rounded",
|
class: "flex items-center pl-3 py-3 pr-2 text-gray-500 hover:bg-indigo-50 rounded",
|
||||||
|
width: {"100%"}.to_string(),
|
||||||
onclick: move |evt| {
|
onclick: move |evt| {
|
||||||
show_user_menu.set(!show_user_menu.get());
|
show_user_menu.set(!show_user_menu.get());
|
||||||
evt.cancel_bubble();
|
evt.cancel_bubble();
|
||||||
@@ -167,3 +168,27 @@ fn key_cannot_be_static() {
|
|||||||
println!("{:?}", parsed.body.diagnostics);
|
println!("{:?}", parsed.body.diagnostics);
|
||||||
assert!(!parsed.body.diagnostics.is_empty());
|
assert!(!parsed.body.diagnostics.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn braced_expressions() {
|
||||||
|
let item = quote::quote! {
|
||||||
|
div {
|
||||||
|
width: {100} - 50,
|
||||||
|
width: {"100%"}.to_string(),
|
||||||
|
width: {|| "100%"}(),
|
||||||
|
}
|
||||||
|
// Partial expressions in braces rsx should be allowed and output as-is
|
||||||
|
// for autocomplete
|
||||||
|
{partial.}
|
||||||
|
div {}
|
||||||
|
{partial.}
|
||||||
|
// Comments should be ignored
|
||||||
|
div {}
|
||||||
|
{partial.}
|
||||||
|
"hello world"
|
||||||
|
{partial.}
|
||||||
|
if true {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let _cb: CallBody = syn::parse2(item).unwrap();
|
||||||
|
}
|
||||||
Reference in new issue
Block a user