Files
dioxus/packages/core-macro/src/rsx/ambiguous.rs
T

83 lines
2.7 KiB
Rust

//! Parse anything that has a pattern of < Ident, Bracket >
//! ========================================================
//!
//! Whenever a `name {}` pattern emerges, we need to parse it into an element, a component, or a fragment.
//! This feature must support:
//! - Namepsaced/pathed components
//! - Differentiating between built-in and custom elements
use super::*;
use proc_macro2::TokenStream as TokenStream2;
use quote::ToTokens;
use syn::{
parse::{Parse, ParseStream},
Error, Ident, LitStr, Result, Token,
};
pub enum AmbiguousElement {
Element(Element),
Component(Component),
Fragment(Fragment),
}
impl Parse for AmbiguousElement {
fn parse(input: ParseStream) -> Result<Self> {
// Try to parse as an absolute path and immediately defer to the componetn
if input.peek(Token![::]) {
return input
.parse::<Component>()
.map(|c| AmbiguousElement::Component(c));
}
// If not an absolute path, then parse the ident and check if it's a valid tag
if let Ok(pat) = input.fork().parse::<syn::Path>() {
if pat.segments.len() > 1 {
return input
.parse::<Component>()
.map(|c| AmbiguousElement::Component(c));
}
}
if let Ok(name) = input.fork().parse::<Ident>() {
let name_str = name.to_string();
match is_valid_tag(&name_str) {
true => input
.parse::<Element>()
.map(|c| AmbiguousElement::Element(c)),
false => {
let first_char = name_str.chars().next().unwrap();
if first_char.is_ascii_uppercase() {
input
.parse::<Component>()
.map(|c| AmbiguousElement::Component(c))
} else {
let name = input.parse::<Ident>().unwrap();
Err(Error::new(
name.span(),
"Components must be uppercased, perhaps you mispelled a html tag",
))
}
}
}
} else {
if input.peek(LitStr) {
panic!("it's actually a litstr");
}
Err(Error::new(input.span(), "Not a valid Html tag"))
}
}
}
impl ToTokens for AmbiguousElement {
fn to_tokens(&self, tokens: &mut TokenStream2) {
match self {
AmbiguousElement::Element(el) => el.to_tokens(tokens),
AmbiguousElement::Component(comp) => comp.to_tokens(tokens),
AmbiguousElement::Fragment(frag) => frag.to_tokens(tokens),
}
}
}