Skip to content

Commit

Permalink
Merge pull request #2884 from leptos-rs/rstml-0.12
Browse files Browse the repository at this point in the history
update to rstml and improve recoverability in attributes
  • Loading branch information
gbj authored Aug 28, 2024
2 parents a7db918 + 7b03e63 commit ceff827
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 31 deletions.
2 changes: 1 addition & 1 deletion leptos_hot_reload/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ syn = { version = "2.0", features = [
"printing",
] }
quote = "1.0"
rstml = "0.11.2"
rstml = "0.12.0"
proc-macro2 = { version = "1.0", features = ["span-locations", "nightly"] }
parking_lot = "0.12.3"
walkdir = "2.5"
Expand Down
4 changes: 2 additions & 2 deletions leptos_hot_reload/src/parsing.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rstml::node::{NodeElement, NodeName};
use rstml::node::{CustomNode, NodeElement, NodeName};

/// Converts `syn::Block` to simple expression
///
Expand Down Expand Up @@ -65,6 +65,6 @@ pub fn is_component_tag_name(name: &NodeName) -> bool {
}

#[must_use]
pub fn is_component_node(node: &NodeElement) -> bool {
pub fn is_component_node(node: &NodeElement<impl CustomNode>) -> bool {
is_component_tag_name(node.name())
}
2 changes: 1 addition & 1 deletion leptos_macro/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ proc-macro-error = { version = "1.0", default-features = false }
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "2.0", features = ["full"] }
rstml = "0.11.2"
rstml = "0.12.0"
leptos_hot_reload = { workspace = true }
server_fn_macro = { workspace = true }
convert_case = "0.6.0"
Expand Down
14 changes: 12 additions & 2 deletions leptos_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ mod slot;
/// Attributes can take a wide variety of primitive types that can be converted to strings. They can also
/// take an `Option`, in which case `Some` sets the attribute and `None` removes the attribute.
///
/// Note that in some cases, rust-analyzer support may be better if attribute values are surrounded with braces (`{}`).
/// Unlike in JSX, attribute values are not required to be in braces, but braces can be used and may improve this LSP support.
///
/// ```rust,ignore
/// # use leptos::prelude::*;
///
Expand Down Expand Up @@ -306,10 +309,17 @@ pub fn view(tokens: TokenStream) -> TokenStream {
global_class.as_ref(),
normalized_call_site(proc_macro::Span::call_site()),
);

// The allow lint needs to be put here instead of at the expansion of
// view::attribute_value(). Adding this next to the expanded expression
// seems to break rust-analyzer, but it works when the allow is put here.
quote! {
{
#(#errors;)*
#nodes_output
#[allow(unused_braces)]
{
#(#errors;)*
#nodes_output
}
}
}
.into()
Expand Down
5 changes: 3 additions & 2 deletions leptos_macro/src/view/component_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ use crate::view::attribute_absolute;
use proc_macro2::{Ident, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use rstml::node::{
KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement, NodeName,
CustomNode, KeyedAttributeValue, NodeAttribute, NodeBlock, NodeElement,
NodeName,
};
use std::collections::HashMap;
use syn::{spanned::Spanned, Expr, ExprPath, ExprRange, RangeLimits, Stmt};

pub(crate) fn component_to_tokens(
node: &NodeElement,
node: &NodeElement<impl CustomNode>,
global_class: Option<&TokenTree>,
) -> TokenStream {
let name = node.name();
Expand Down
52 changes: 32 additions & 20 deletions leptos_macro/src/view/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use proc_macro2::{Ident, Span, TokenStream, TokenTree};
use proc_macro_error::abort;
use quote::{quote, quote_spanned, ToTokens};
use rstml::node::{
KeyedAttribute, Node, NodeAttribute, NodeBlock, NodeElement, NodeName,
NodeNameFragment,
CustomNode, KVAttributeValue, KeyedAttribute, Node, NodeAttribute,
NodeBlock, NodeElement, NodeName, NodeNameFragment,
};
use std::collections::{HashMap, HashSet};
use syn::{
Expand Down Expand Up @@ -89,7 +89,7 @@ pub fn render_view(
}

fn element_children_to_tokens(
nodes: &[Node],
nodes: &[Node<impl CustomNode>],
parent_type: TagType,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand Down Expand Up @@ -117,7 +117,7 @@ fn element_children_to_tokens(
}

fn fragment_to_tokens(
nodes: &[Node],
nodes: &[Node<impl CustomNode>],
parent_type: TagType,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand All @@ -142,7 +142,7 @@ fn fragment_to_tokens(
}

fn children_to_tokens(
nodes: &[Node],
nodes: &[Node<impl CustomNode>],
parent_type: TagType,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand Down Expand Up @@ -186,7 +186,7 @@ fn children_to_tokens(
}

fn node_to_tokens(
node: &Node,
node: &Node<impl CustomNode>,
parent_type: TagType,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand Down Expand Up @@ -219,6 +219,7 @@ fn node_to_tokens(
global_class,
view_marker,
),
Node::Custom(node) => Some(node.to_token_stream()),
}
}

Expand All @@ -236,7 +237,7 @@ fn text_to_tokens(text: &LitStr) -> TokenStream {
}

pub(crate) fn element_to_tokens(
node: &NodeElement,
node: &NodeElement<impl CustomNode>,
mut parent_type: TagType,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand Down Expand Up @@ -411,7 +412,7 @@ pub(crate) fn element_to_tokens(
}
}

fn is_spread_marker(node: &NodeElement) -> bool {
fn is_spread_marker(node: &NodeElement<impl CustomNode>) -> bool {
match node.name() {
NodeName::Block(block) => matches!(
block.stmts.first(),
Expand Down Expand Up @@ -773,7 +774,7 @@ fn is_custom_element(tag: &str) -> bool {
tag.contains('-')
}

fn is_self_closing(node: &NodeElement) -> bool {
fn is_self_closing(node: &NodeElement<impl CustomNode>) -> bool {
// self-closing tags
// https://developer.mozilla.org/en-US/docs/Glossary/Empty_element
[
Expand Down Expand Up @@ -921,20 +922,31 @@ fn attribute_name(name: &NodeName) -> TokenStream {
}

fn attribute_value(attr: &KeyedAttribute) -> TokenStream {
match attr.value() {
Some(value) => {
if let Expr::Lit(lit) = value {
if cfg!(feature = "nightly") {
if let Lit::Str(str) = &lit.lit {
return quote! {
::leptos::tachys::view::static_types::Static::<#str>
};
match attr.possible_value.to_value() {
None => quote! { true },
Some(value) => match &value.value {
KVAttributeValue::Expr(expr) => {
if let Expr::Lit(lit) = expr {
if cfg!(feature = "nightly") {
if let Lit::Str(str) = &lit.lit {
return quote! {
::leptos::tachys::view::static_types::Static::<#str>
};
}
}
}

quote! {
{#expr}
}
}
quote! { #value }
}
None => quote! { true },
// any value in braces: expand as-is to give proper r-a support
KVAttributeValue::InvalidBraced(block) => {
quote! {
#block
}
}
},
}
}

Expand Down
8 changes: 5 additions & 3 deletions leptos_macro/src/view/slot_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use super::{convert_to_snake_case, ident_from_tag_name};
use crate::view::{fragment_to_tokens, TagType};
use proc_macro2::{Ident, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use rstml::node::{KeyedAttribute, NodeAttribute, NodeElement};
use rstml::node::{CustomNode, KeyedAttribute, NodeAttribute, NodeElement};
use std::collections::HashMap;
use syn::spanned::Spanned;

pub(crate) fn slot_to_tokens(
node: &NodeElement,
node: &NodeElement<impl CustomNode>,
slot: &KeyedAttribute,
parent_slots: Option<&mut HashMap<String, Vec<TokenStream>>>,
global_class: Option<&TokenTree>,
Expand Down Expand Up @@ -213,7 +213,9 @@ pub(crate) fn is_slot(node: &KeyedAttribute) -> bool {
key == "slot" || key.starts_with("slot:")
}

pub(crate) fn get_slot(node: &NodeElement) -> Option<&KeyedAttribute> {
pub(crate) fn get_slot(
node: &NodeElement<impl CustomNode>,
) -> Option<&KeyedAttribute> {
node.attributes().iter().find_map(|node| {
if let NodeAttribute::Attribute(node) = node {
if is_slot(node) {
Expand Down

0 comments on commit ceff827

Please sign in to comment.