use leptos_hot_reload::parsing::is_component_tag_name;
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use rstml::node::{NodeElement, NodeName};
use syn::spanned::Spanned;
pub(crate) struct IdeTagHelper(Vec<TokenStream>);
impl IdeTagHelper {
pub fn new() -> Self {
Self(Vec::new())
}
pub fn save_tag_completion(&mut self, name: &NodeName) {
if is_component_tag_name(name) {
proc_macro_error::emit_warning!(
name.span(),
"BUG: Component tag is used in regular tag completion."
);
}
for path in Self::completion_stmts(name) {
self.0.push(quote! {
let _ = #path;
});
}
}
pub fn save_element_completion(&mut self, node: &NodeElement) {
self.save_tag_completion(node.name());
if let Some(close_tag) = node.close_tag.as_ref().map(|c| &c.name) {
self.save_tag_completion(close_tag)
}
}
fn create_regular_tag_fn_path(name: &Ident) -> TokenStream {
let tag_name = name.to_string();
let namespace = if crate::view::is_svg_element(&tag_name) {
quote! { ::leptos::leptos_dom::svg }
} else if crate::view::is_math_ml_element(&tag_name) {
quote! { ::leptos::leptos_dom::math }
} else {
quote! { ::leptos::leptos_dom::html }
};
quote! { #namespace::#name }
}
fn create_custom_tag_fn_path(span: Span) -> TokenStream {
let custom_ident = Ident::new("custom", span);
quote! { ::leptos::leptos_dom::html::#custom_ident::<::leptos::leptos_dom::html::Custom> }
}
fn completion_stmts(name: &NodeName) -> Vec<TokenStream> {
match name {
NodeName::Block(_) => vec![],
NodeName::Punctuated(c) => c
.pairs()
.flat_map(|c| {
let mut idents =
vec![Self::create_custom_tag_fn_path(c.value().span())];
if let Some(p) = c.punct() {
idents.push(Self::create_custom_tag_fn_path(p.span()))
}
idents
})
.collect(),
NodeName::Path(e) => e
.path
.segments
.last()
.map(|p| &p.ident)
.map(Self::create_regular_tag_fn_path)
.into_iter()
.collect(),
}
}
}
impl IntoIterator for IdeTagHelper {
type Item = TokenStream;
type IntoIter = <Vec<TokenStream> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}