diff --git a/Cargo.toml b/Cargo.toml index c840f40..1977c3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,14 +13,14 @@ license = "MIT" bench = false [dependencies] -proc-macro2 = "1.0.47" -quote = "1.0.21" -syn = { version = "1.0.102", features = ["full", "parsing", "extra-traits"] } -thiserror = "1.0.37" +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full", "parsing", "extra-traits"] } +thiserror = "1.0" [dev-dependencies] -criterion = "0.4.0" -eyre = "0.6.8" +criterion = "0.4" +eyre = "0.6" [[bench]] name = "bench" diff --git a/examples/html-to-string-macro/Cargo.toml b/examples/html-to-string-macro/Cargo.toml index 1352299..55da930 100644 --- a/examples/html-to-string-macro/Cargo.toml +++ b/examples/html-to-string-macro/Cargo.toml @@ -13,7 +13,7 @@ license = "MIT" proc-macro = true [dependencies] -proc-macro2 = "1.0.47" -quote = "1.0.21" -syn = "1.0.102" +proc-macro2 = "1.0" +quote = "1.0" +syn = "2.0" syn-rsx = { path = "../../" } diff --git a/src/node.rs b/src/node.rs index 4d42494..3ad34a4 100644 --- a/src/node.rs +++ b/src/node.rs @@ -3,10 +3,9 @@ use std::{convert::TryFrom, fmt, ops::Deref}; use proc_macro2::{Punct, Span, TokenStream}; -use quote::ToTokens; +use quote::{ToTokens, quote_spanned}; use syn::{ punctuated::{Pair, Punctuated}, - spanned::Spanned, Expr, ExprBlock, ExprLit, ExprPath, Ident, Lit, }; @@ -87,16 +86,16 @@ impl Node { } } -impl Spanned for Node { - fn span(&self) -> Span { +impl ToTokens for Node { + fn to_tokens(&self, tokens: &mut TokenStream) { match self { - Node::Element(node) => node.span(), - Node::Attribute(node) => node.span(), - Node::Text(node) => node.span(), - Node::Comment(node) => node.span(), - Node::Doctype(node) => node.span(), - Node::Block(node) => node.span(), - Node::Fragment(node) => node.span(), + Node::Attribute(a) => a.to_tokens(tokens), + Node::Block(b) => b.to_tokens(tokens), + Node::Comment(c) => c.to_tokens(tokens), + Node::Doctype(d) => d.to_tokens(tokens), + Node::Fragment(f) => f.to_tokens(tokens), + Node::Element(e) => e.to_tokens(tokens), + Node::Text(t) => t.to_tokens(tokens), } } } @@ -144,9 +143,21 @@ impl fmt::Display for NodeElement { } } -impl Spanned for NodeElement { - fn span(&self) -> Span { - self.span +impl ToTokens for NodeElement { + fn to_tokens(&self, tokens: &mut TokenStream) { + + let name = &self.name; + let attributes = &self.attributes; + let children = &self.children; + + // self closing + if children.is_empty() { + tokens.extend(quote_spanned!(self.span => + <#name #(#attributes)* /> )) + } else { + tokens.extend(quote_spanned!(self.span => + <#name #(#attributes)*> #(#children)* )) + } } } @@ -172,9 +183,20 @@ impl fmt::Display for NodeAttribute { } } -impl Spanned for NodeAttribute { - fn span(&self) -> Span { - self.span +impl ToTokens for NodeAttribute { + fn to_tokens(&self, tokens: &mut TokenStream) { + + let key = &self.key; + let value = &self.value; + + // self closing + if let Some(value) = value{ + tokens.extend(quote_spanned!(self.span => + #key = #value )) + } else { + tokens.extend(quote_spanned!(self.span => + #key )) + } } } @@ -197,9 +219,9 @@ impl fmt::Display for NodeText { } } -impl Spanned for NodeText { - fn span(&self) -> Span { - self.value.span() +impl ToTokens for NodeText { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.value.to_tokens(tokens); } } @@ -224,12 +246,14 @@ impl fmt::Display for NodeComment { } } -impl Spanned for NodeComment { - fn span(&self) -> Span { - self.span +impl ToTokens for NodeComment { + fn to_tokens(&self, tokens: &mut TokenStream) { + let value = &self.value; + tokens.extend(quote_spanned!(self.span=> )) } } + /// Doctype node. /// /// Doctype declaration: `` (case insensitive), `html` is the @@ -251,9 +275,10 @@ impl fmt::Display for NodeDoctype { } } -impl Spanned for NodeDoctype { - fn span(&self) -> Span { - self.span +impl ToTokens for NodeDoctype { + fn to_tokens(&self, tokens: &mut TokenStream) { + let value = &self.value; + tokens.extend(quote_spanned!(self.span=> )) } } @@ -277,9 +302,10 @@ impl fmt::Display for NodeFragment { } } -impl Spanned for NodeFragment { - fn span(&self) -> Span { - self.span +impl ToTokens for NodeFragment { + fn to_tokens(&self, tokens: &mut TokenStream) { + let childrens = &self.children; + tokens.extend(quote_spanned!(self.span => <> #(#childrens)* )) } } @@ -298,9 +324,9 @@ impl fmt::Display for NodeBlock { } } -impl Spanned for NodeBlock { - fn span(&self) -> Span { - self.value.span() +impl ToTokens for NodeBlock { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.value.to_tokens(tokens) } } @@ -412,6 +438,13 @@ impl NodeValueExpr { } } +impl ToTokens for NodeValueExpr { + fn to_tokens(&self, tokens: &mut TokenStream) { + let obj = self.as_ref(); + obj.to_tokens(tokens) + } +} + impl AsRef for NodeValueExpr { fn as_ref(&self) -> &Expr { &self.expr diff --git a/src/parser.rs b/src/parser.rs index 7d8336c..6ce5d58 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2,14 +2,14 @@ use std::vec; -use proc_macro2::{Punct, Span, TokenStream, TokenTree}; +use proc_macro2::{Punct, Span, TokenStream, TokenTree, Group}; use syn::{ braced, ext::IdentExt, parse::{discouraged::Speculative, Parse, ParseStream, Parser as _, Peek}, punctuated::Punctuated, spanned::Spanned, - token::{Brace, Colon, Colon2}, + token::{Brace, Colon, PathSep}, Block, Error, Expr, ExprBlock, ExprLit, ExprPath, Ident, Path, PathSegment, Result, Token, }; @@ -126,9 +126,8 @@ impl Parser { match transform_fn(&forked_block_content) { Ok(transformed_tokens) => match transformed_tokens { Some(tokens) => { - let parser = move |input: ParseStream| { - Ok(self.block_content_to_block(input, block_content.span())) - }; + let parser = + move |input: ParseStream| Ok(self.block_content_to_block(input, block_content.span())); let transformed_content = parser.parse2(tokens)?; block_content.advance_to(&forked_block_content); transformed_content @@ -153,11 +152,13 @@ impl Parser { /// Parse the given stream and span as [`Expr::Block`]. fn block_content_to_block(&self, input: ParseStream, span: Span) -> Result { + let mut delim_span = Group::new(proc_macro2::Delimiter::None, TokenStream::new()); + delim_span.set_span(span); Ok(ExprBlock { attrs: vec![], label: None, block: Block { - brace_token: Brace { span }, + brace_token: Brace { span: delim_span.delim_span() }, stmts: Block::parse_within(input)?, }, } @@ -443,18 +444,20 @@ impl Parser { /// Parse the stream as [`NodeName`]. fn node_name(&self, input: ParseStream) -> Result { - if input.peek2(Colon2) { - self.node_name_punctuated_ident:: Colon2, PathSegment>(input, Colon2) - .map(|segments| { - NodeName::Path(ExprPath { - attrs: vec![], - qself: None, - path: Path { - leading_colon: None, - segments, - }, - }) + if input.peek2(PathSep) { + self.node_name_punctuated_ident:: PathSep, PathSegment>( + input, PathSep, + ) + .map(|segments| { + NodeName::Path(ExprPath { + attrs: vec![], + qself: None, + path: Path { + leading_colon: None, + segments, + }, }) + }) } else if input.peek2(Colon) || input.peek2(Dash) { self.node_name_punctuated_ident_with_alternate:: Colon, fn(_) -> Dash, Ident>( input, Colon, Dash, diff --git a/tests/test.rs b/tests/test.rs index 1051716..655e8a4 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2,7 +2,7 @@ use std::convert::TryFrom; use eyre::Result; use quote::quote; -use syn::ExprBlock; +use syn::{ExprBlock, Stmt}; use syn_rsx::{ parse2, parse2_with_config, Node, NodeAttribute, NodeElement, NodeType, ParserConfig, }; @@ -245,7 +245,7 @@ fn test_type_of_top_level_nodes() -> Result<()> { #[test] fn test_transform_block_some() -> Result<()> { - use syn::{Expr, Lit, Stmt, Token}; + use syn::{Expr, Lit, Token}; let tokens = quote! {
{%}
@@ -263,7 +263,7 @@ fn test_transform_block_some() -> Result<()> { match block.value.as_ref() { Expr::Block(expr) => { match &expr.block.stmts[0] { - Stmt::Expr(Expr::Lit(expr)) => match &expr.lit { + Stmt::Expr(Expr::Lit(expr), _) => match &expr.lit { Lit::Str(lit_str) => Some(lit_str.value()), _ => None, },