Skip to content

Commit 65df573

Browse files
committed
always expand to raw ident
1 parent 33dbf7b commit 65df573

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

leptos-mview-core/src/ast/ident.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::hash::Hash;
2-
31
use proc_macro2::{Span, TokenStream};
42
use proc_macro_error::emit_error;
53
use quote::{quote, ToTokens};
@@ -46,7 +44,9 @@ pub struct KebabIdent {
4644
}
4745

4846
impl KebabIdent {
49-
/// Returns a reference to the repr of this [`KebabIdent`].
47+
/// Returns the string representation of the identifier, in kebab-case.
48+
///
49+
/// This is not a raw identifier, i.e. it does not start with "r#".
5050
pub fn repr(&self) -> &str { self.repr.as_ref() }
5151

5252
/// Returns the span of this [`KebabIdent`].
@@ -94,13 +94,15 @@ impl KebabIdent {
9494
/// The span will only be the first 'section' on stable, but correctly
9595
/// covers the full ident on nightly. See [`KebabIdent::span`] for more
9696
/// details.
97+
///
98+
/// The ident will also be a raw identifier.
9799
pub fn to_snake_ident(&self) -> syn::Ident {
98100
let snake_string = self.repr().replace('-', "_");
99101
// This will always be valid as the first 'section' must be a `-` or rust ident,
100102
// which means it starts with `_` or another valid identifier beginning. The int
101103
// literals within the ident (e.g. between `-`s, like `blue-100`) are allowed
102104
// since the ident does not start with a number.
103-
syn::Ident::new(&snake_string, self.span())
105+
syn::Ident::new_raw(&snake_string, self.span())
104106
}
105107
}
106108

@@ -111,7 +113,9 @@ impl Parse for KebabIdent {
111113

112114
// Start with `-` or letter.
113115
if let Some(ident) = rollback_err(input, syn::Ident::parse_any) {
114-
repr.push_str(&ident.to_string());
116+
// only store the non-raw representation: in expansion,
117+
// this should expand to a raw ident.
118+
repr.push_str(&ident.unraw().to_string());
115119
spans.push(ident.span());
116120
} else if let Some(dash) = rollback_err(input, <Token![-]>::parse) {
117121
repr.push('-');
@@ -142,7 +146,11 @@ impl Parse for KebabIdent {
142146

143147
// add ident or number
144148
if let Some(ident) = rollback_err(input, syn::Ident::parse_any) {
145-
repr.push_str(&ident.to_string());
149+
let unraw = ident.unraw();
150+
if ident != unraw {
151+
emit_error!(ident.span(), "invalid raw identifier within kebab-ident");
152+
}
153+
repr.push_str(&unraw.to_string());
146154
spans.push(ident.span());
147155
} else if let Some(int) = rollback_err(input, syn::LitInt::parse) {
148156
repr.push_str(&int.to_string());
@@ -160,7 +168,7 @@ impl From<proc_macro2::Ident> for KebabIdent {
160168
// repr is not empty as `proc_macro2::Ident` must be a valid Rust identifier,
161169
// and "" is not.
162170
Self {
163-
repr: value.to_string(),
171+
repr: value.unraw().to_string(),
164172
spans: vec![value.span()],
165173
}
166174
}
@@ -174,10 +182,6 @@ impl PartialEq for KebabIdent {
174182

175183
impl Eq for KebabIdent {}
176184

177-
impl Hash for KebabIdent {
178-
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.repr.hash(state); }
179-
}
180-
181185
// Parse either a kebab-case ident or a str literal.
182186
#[derive(Clone)]
183187
pub enum KebabIdentOrStr {
@@ -250,6 +254,8 @@ impl Parse for BracedKebabIdent {
250254

251255
#[cfg(test)]
252256
mod tests {
257+
use std::iter;
258+
253259
use super::KebabIdent;
254260

255261
#[test]
@@ -294,4 +300,14 @@ mod tests {
294300
assert_eq!(ident.repr(), stream.replace(' ', ""));
295301
}
296302
}
303+
304+
#[test]
305+
fn raw() {
306+
let raws = ["r#move", "move", "r#some-thing"];
307+
let results = ["move", "move", "some-thing"];
308+
for (stream, res) in iter::zip(raws, results) {
309+
let ident = syn::parse_str::<KebabIdent>(stream).unwrap();
310+
assert_eq!(ident.repr(), res);
311+
}
312+
}
297313
}

leptos-mview-core/src/ast/tag.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use proc_macro2::Span;
22
use syn::{
3+
ext::IdentExt,
34
parse::{Parse, ParseStream},
45
spanned::Spanned,
56
Token,
@@ -64,7 +65,7 @@ impl Parse for Tag {
6465
let kind = TagKind::from(ident.repr());
6566
Ok(match kind {
6667
TagKind::Html => Self::Html(ident.to_snake_ident()),
67-
TagKind::Component => Self::Component(syn::Path::from(ident.to_snake_ident())),
68+
TagKind::Component => Self::Component(syn::Path::from(ident.to_snake_ident().unraw())),
6869
TagKind::Svg => Self::Svg(ident.to_snake_ident()),
6970
TagKind::Math => Self::Math(ident.to_snake_ident()),
7071
TagKind::WebComponent => Self::WebComponent(ident),

leptos-mview-core/src/expand.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::collections::HashMap;
88
use proc_macro2::{Span, TokenStream};
99
use proc_macro_error::emit_error;
1010
use quote::{quote, quote_spanned, ToTokens};
11-
use syn::spanned::Spanned;
11+
use syn::{ext::IdentExt, spanned::Spanned};
1212

1313
use crate::ast::{
1414
attribute::{directive::Directive, selector::SelectorShorthand},
@@ -378,7 +378,7 @@ fn slots_to_tokens<'a>(children: impl Iterator<Item = &'a Element>) -> TokenStre
378378
.into_iter()
379379
.map(|(slot_name, slot_tokens)| {
380380
let method = syn::Ident::new_raw(
381-
&utils::upper_camel_to_snake_case(&slot_name.to_string()),
381+
&utils::upper_camel_to_snake_case(&slot_name.unraw().to_string()),
382382
slot_name.span(),
383383
);
384384

0 commit comments

Comments
 (0)