Skip to content

Commit

Permalink
Merge pull request #2840 from chrisp60/0_6_14-fix-proc-macro-spans-ra
Browse files Browse the repository at this point in the history
[0.6] fix: Rust-Analyzer hover information / redundant spans
  • Loading branch information
gbj authored Aug 17, 2024
2 parents 7789d58 + 0653e67 commit 3aef9e2
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 62 deletions.
38 changes: 15 additions & 23 deletions leptos_macro/src/view/client_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ pub(crate) fn fragment_to_tokens(
let mut nodes = nodes
.iter()
.filter_map(|node| {
let span = node.span();
let node = node_to_tokens(
node,
parent_type,
Expand All @@ -52,10 +51,8 @@ pub(crate) fn fragment_to_tokens(
None,
)?;

let node = quote_spanned!(span => { #node });

Some(quote! {
::leptos::IntoView::into_view(#[allow(unused_braces)] #node)
::leptos::IntoView::into_view(#[allow(unused_braces)] { #node })
})
})
.peekable();
Expand Down Expand Up @@ -306,9 +303,7 @@ pub(crate) fn element_to_tokens(
global_class,
None,
)
.unwrap_or(quote_spanned! {
Span::call_site()=> ::leptos::leptos_dom::Unit
}),
.unwrap_or(quote! { ::leptos::leptos_dom::Unit }),
),
Node::Text(node) => Some(quote! { #node }),
Node::RawText(node) => {
Expand Down Expand Up @@ -337,16 +332,17 @@ pub(crate) fn element_to_tokens(
quote! {}
};
let ide_helper_close_tag = ide_helper_close_tag.into_iter();
let result = quote_spanned! {node.span()=> {
#(#ide_helper_close_tag)*
#name
#(#attrs)*
#(#bindings)*
#(#class_attrs)*
#(#style_attrs)*
#global_class_expr
#(#children)*
#view_marker
let result = quote! {
{
#(#ide_helper_close_tag)*
#name
#(#attrs)*
#(#bindings)*
#(#class_attrs)*
#(#style_attrs)*
#global_class_expr
#(#children)*
#view_marker
}
};

Expand Down Expand Up @@ -406,18 +402,14 @@ pub(crate) fn attribute_to_tokens(
let event_type = if is_custom {
event_type
} else if let Some(ev_name) = event_name_ident {
quote_spanned! {
ev_name.span()=> #ev_name
}
quote! { #ev_name }
} else {
event_type
};

let event_type = if is_force_undelegated {
let undelegated = if let Some(undelegated) = undelegated_ident {
quote_spanned! {
undelegated.span()=> #undelegated
}
quote! { #undelegated }
} else {
quote! { undelegated }
};
Expand Down
43 changes: 17 additions & 26 deletions leptos_macro/src/view/component_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use super::{
};
use crate::view::directive_call_from_attribute_node;
use proc_macro2::{Ident, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use quote::{format_ident, quote, quote_spanned, ToTokens};
use rstml::node::{NodeAttribute, NodeElement};
use std::collections::HashMap;
use syn::spanned::Spanned;
Expand Down Expand Up @@ -70,10 +70,8 @@ pub(crate) fn component_to_tokens(
})
.unwrap_or_else(|| quote! { #name });

let value = quote_spanned!(value.span()=> { #value });

quote_spanned! {attr.span()=>
.#name(#[allow(unused_braces)] #value)
quote! {
.#name(#[allow(unused_braces)] { #value })
}
});

Expand Down Expand Up @@ -102,7 +100,13 @@ pub(crate) fn component_to_tokens(
.filter(|attr| attr.key.to_string().starts_with("on:"))
.map(|attr| {
let (event_type, handler) = event_from_attribute_node(attr, true);
let on = quote_spanned!(attr.key.span()=> on);
// HACK(chrisp60): rstml and leptos has a different definition on attribute keys.
// This retains precise span information for the "on" in "on:some_event_name".
//
// A similar hack is done in `event_from_attribute_node` to retain the precise
// event name span.
let on = attr.key.to_token_stream().into_iter().next();

quote! {
.#on(#event_type, #handler)
}
Expand Down Expand Up @@ -169,8 +173,7 @@ pub(crate) fn component_to_tokens(
items_to_bind.iter().map(|ident| quote! { #ident, });

let clonables = items_to_clone.iter().map(|ident| {
let ident_ref = quote_spanned!(ident.span()=> &#ident);
quote! { let #ident = ::core::clone::Clone::clone(#ident_ref); }
quote! { let #ident = ::core::clone::Clone::clone(&#ident); }
});

if bindables.len() > 0 {
Expand Down Expand Up @@ -202,7 +205,7 @@ pub(crate) fn component_to_tokens(
.span();
let slot = Ident::new(&slot, span);
let value = if values.len() > 1 {
quote_spanned! {span=>
quote! {
::std::vec![
#(#values)*
]
Expand All @@ -221,28 +224,16 @@ pub(crate) fn component_to_tokens(
quote! {}
};

let name_ref = quote_spanned! {name.span()=>
&#name
};

let build = quote_spanned! {name.span()=>
.build()
};

let component_props_builder = quote_spanned! {name.span()=>
::leptos::component_props_builder(#name_ref #generics)
};

#[allow(unused_mut)] // used in debug
let mut component = quote_spanned! {node.span()=>
let mut component = quote! {
::leptos::component_view(
#[allow(clippy::needless_borrows_for_generic_args)]
#name_ref,
#component_props_builder
&#name,
::leptos::component_props_builder(&#name #generics)
#(#props)*
#(#slots)*
#children
#build
.build()
#dyn_attrs
#(#spread_bindings)*
)
Expand All @@ -256,7 +247,7 @@ pub(crate) fn component_to_tokens(
if events_and_directives.is_empty() {
component
} else {
quote_spanned! {node.span()=>
quote! {
::leptos::IntoView::into_view(#[allow(unused_braces)] {#component})
#(#events_and_directives)*
}
Expand Down
37 changes: 33 additions & 4 deletions leptos_macro/src/view/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{attribute_value, Mode};
use convert_case::{Case::Snake, Casing};
use proc_macro2::{Ident, Span, TokenStream, TokenTree};
use quote::{quote, quote_spanned};
use quote::{quote, quote_spanned, ToTokens};
use rstml::node::{KeyedAttribute, Node, NodeElement, NodeName};
use syn::{
spanned::Spanned,
Expand Down Expand Up @@ -567,12 +567,41 @@ pub(crate) fn event_from_attribute_node(

let handler = attribute_value(attr);

let (event_type, _, name_undelegated) = parse_event_name(&event_name);
let (event_type, is_custom, name_undelegated) =
parse_event_name(&event_name);

// HACK(chrisp60): in the code above, the original span information is lost
// as the event name is parsed from a stringified version of the tokens.
//
// This assumes that the attribute key is structured as "on:some_event_name" and
// just skips the "on:" part, isolating the "some_event_name" tokens. In turn,
// we keep the span information from the original event identifier.
//
// .nth(2) is because syn parses follows
// token 0: "on"
// token 1: ":"
// token 2: "event"
//
// There are cleaners ways to do this but this is a legacy branch.
let original_tokens = attr
.key
.to_token_stream()
.into_iter()
.nth(2)
.expect("tokens following on:"); // see previous call to .expect in this same function

// is_custom wraps the event type in a struct definition, so don't use
// our original tokens.
let absolute_ev = if is_custom {
quote! { ::leptos::leptos_dom::ev::#event_type }
} else {
quote! { ::leptos::leptos_dom::ev::#original_tokens }
};

let event_type = if force_undelegated || name_undelegated {
quote! { ::leptos::leptos_dom::ev::undelegated(::leptos::leptos_dom::ev::#event_type) }
quote! { ::leptos::leptos_dom::ev::undelegated(#absolute_ev) }
} else {
quote! { ::leptos::leptos_dom::ev::#event_type }
quote! { ::leptos::leptos_dom::ev::#absolute_ev }
};
(event_type, handler)
}
Expand Down
6 changes: 2 additions & 4 deletions leptos_macro/src/view/server_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,14 @@ pub(crate) fn fragment_to_tokens_ssr(
};

let nodes = nodes.iter().map(|node| {
let span = node.span();
let node = root_node_to_tokens_ssr(node, global_class, None);
let node = quote_spanned!(span=> { #node });

quote! {
::leptos::IntoView::into_view(#[allow(unused_braces)] #node)
::leptos::IntoView::into_view(#[allow(unused_braces)] { #node })
}
});

quote_spanned! {original_span=>
quote! {
{
::leptos::Fragment::lazy(|| ::std::vec![
#(#nodes),*
Expand Down
8 changes: 3 additions & 5 deletions leptos_macro/src/view/slot_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ pub(crate) fn slot_to_tokens(
})
.unwrap_or_else(|| quote! { #name });

let value = quote_spanned!(value.span()=> { #value });

quote_spanned! {attr.span()=>
.#name(#[allow(unused_braces)] #value)
quote! {
.#name(#[allow(unused_braces)] { #value })
}
});

Expand Down Expand Up @@ -168,7 +166,7 @@ pub(crate) fn slot_to_tokens(
.span();
let slot = Ident::new(&slot, span);
let value = if values.len() > 1 {
quote_spanned! {span=>
quote! {
::std::vec![
#(#values)*
]
Expand Down

0 comments on commit 3aef9e2

Please sign in to comment.