Skip to content

Commit 5fbc5ca

Browse files
committed
Make macros accept idents where atom is a valid atom
This means that local_name!(html) will work as well as local_name!("html") Signed-off-by: Nico Burns <[email protected]>
1 parent eb5ad11 commit 5fbc5ca

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

string-cache-codegen/lib.rs

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
6969
#![recursion_limit = "128"]
7070

71+
use proc_macro2::{Ident, Literal, TokenStream};
7172
use quote::quote;
7273
use std::collections::BTreeSet;
7374
use std::fs::File;
@@ -185,8 +186,7 @@ impl AtomType {
185186
/// Write generated code to destination [`Vec<u8>`] and return it as [`String`]
186187
///
187188
/// Used mostly for testing or displaying a value.
188-
pub fn write_to_string(&mut self, mut destination: Vec<u8>) -> io::Result<String>
189-
{
189+
pub fn write_to_string(&mut self, mut destination: Vec<u8>) -> io::Result<String> {
190190
destination.write_all(
191191
self.to_tokens()
192192
.to_string()
@@ -223,6 +223,23 @@ impl AtomType {
223223
let empty_string_index = atoms.iter().position(|s| s.is_empty()).unwrap() as u32;
224224
let indices = 0..atoms.len() as u32;
225225

226+
fn is_valid_ident(name: &str) -> bool {
227+
let begins_with_letter_or_underscore = name
228+
.chars()
229+
.next()
230+
.is_some_and(|c| c.is_alphabetic() || c == '_');
231+
let is_alphanumeric = name.chars().all(|c| c.is_alphanumeric() || c == '_');
232+
233+
begins_with_letter_or_underscore && is_alphanumeric
234+
}
235+
236+
let atoms_for_idents: Vec<&str> = atoms.iter().filter(|x| is_valid_ident(x)).collect();
237+
let atom_idents: Vec<Ident> = atoms_for_idents.iter().map(|atom| new_term(atom)).collect();
238+
239+
let istrs_for_idents: Vec<&str> =
240+
inline_strs.iter().filter(|x| is_valid_ident(x)).collect();
241+
let istr_idents: Vec<Ident> = istrs_for_idents.iter().map(|atom| new_term(atom)).collect();
242+
226243
let hashes: Vec<u32> = atoms
227244
.iter()
228245
.map(|string| {
@@ -249,8 +266,9 @@ impl AtomType {
249266
Some(ref doc) => quote!(#[doc = #doc]),
250267
None => quote!(),
251268
};
252-
let new_term =
253-
|string: &str| proc_macro2::Ident::new(string, proc_macro2::Span::call_site());
269+
fn new_term(string: &str) -> Ident {
270+
Ident::new(string, proc_macro2::Span::call_site())
271+
}
254272
let static_set_name = new_term(&format!("{}StaticSet", type_name));
255273
let type_name = new_term(type_name);
256274
let macro_name = new_term(&*self.macro_name);
@@ -264,6 +282,16 @@ impl AtomType {
264282
new_term(&name)
265283
};
266284
let const_names: Vec<_> = atoms.iter().copied().map(new_const_name).collect();
285+
let ident_const_names: Vec<_> = atoms_for_idents
286+
.iter()
287+
.copied()
288+
.map(new_const_name)
289+
.collect();
290+
let ident_inline_const_names: Vec<_> = istrs_for_idents
291+
.iter()
292+
.copied()
293+
.map(new_const_name)
294+
.collect();
267295

268296
// Inline strings
269297
let (inline_const_names, inline_values_and_lengths): (Vec<_>, Vec<_>) = inline_strs
@@ -323,6 +351,12 @@ impl AtomType {
323351
#(
324352
(#inline_strs) => { #module::#inline_const_names };
325353
)*
354+
#(
355+
(#atom_idents) => { #module::#ident_const_names };
356+
)*
357+
#(
358+
(#istr_idents) => { #module::#ident_inline_const_names };
359+
)*
326360
}
327361
}
328362
}
@@ -340,11 +374,13 @@ impl AtomType {
340374
fn test_iteration_order() {
341375
let x1 = crate::AtomType::new("foo::Atom", "foo_atom!")
342376
.atoms(&["x", "xlink", "svg", "test"])
343-
.write_to_string(Vec::new()).expect("write to string cache x1");
377+
.write_to_string(Vec::new())
378+
.expect("write to string cache x1");
344379

345380
let x2 = crate::AtomType::new("foo::Atom", "foo_atom!")
346381
.atoms(&["x", "xlink", "svg", "test"])
347-
.write_to_string(Vec::new()).expect("write to string cache x2");
382+
.write_to_string(Vec::new())
383+
.expect("write to string cache x2");
348384

349385
assert_eq!(x1, x2);
350386
}

0 commit comments

Comments
 (0)