Skip to content

Commit 533b64e

Browse files
authored
Make macros accept idents where atom value is a valid ident (#296)
* 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]> * Fix tests build Signed-off-by: Nico Burns <[email protected]> --------- Signed-off-by: Nico Burns <[email protected]>
1 parent eb5ad11 commit 533b64e

File tree

2 files changed

+50
-7
lines changed

2 files changed

+50
-7
lines changed

integration-tests/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ unstable = []
1919
string_cache = { version = "0.9", path = ".." }
2020

2121
[dev-dependencies]
22-
rand = "0.8"
22+
rand = { version = "0.8", features = ["small_rng"] }
2323
string_cache_codegen = { version = "0.6", path = "../string-cache-codegen" }
2424

2525
[build-dependencies]

string-cache-codegen/lib.rs

Lines changed: 49 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;
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,30 @@ 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
237+
.iter()
238+
.copied()
239+
.filter(|x| is_valid_ident(x))
240+
.collect();
241+
let atom_idents: Vec<Ident> = atoms_for_idents.iter().map(|atom| new_term(atom)).collect();
242+
243+
let istrs_for_idents: Vec<&str> = inline_strs
244+
.iter()
245+
.copied()
246+
.filter(|x| is_valid_ident(x))
247+
.collect();
248+
let istr_idents: Vec<Ident> = istrs_for_idents.iter().map(|atom| new_term(atom)).collect();
249+
226250
let hashes: Vec<u32> = atoms
227251
.iter()
228252
.map(|string| {
@@ -249,8 +273,9 @@ impl AtomType {
249273
Some(ref doc) => quote!(#[doc = #doc]),
250274
None => quote!(),
251275
};
252-
let new_term =
253-
|string: &str| proc_macro2::Ident::new(string, proc_macro2::Span::call_site());
276+
fn new_term(string: &str) -> Ident {
277+
Ident::new(string, proc_macro2::Span::call_site())
278+
}
254279
let static_set_name = new_term(&format!("{}StaticSet", type_name));
255280
let type_name = new_term(type_name);
256281
let macro_name = new_term(&*self.macro_name);
@@ -264,6 +289,16 @@ impl AtomType {
264289
new_term(&name)
265290
};
266291
let const_names: Vec<_> = atoms.iter().copied().map(new_const_name).collect();
292+
let ident_const_names: Vec<_> = atoms_for_idents
293+
.iter()
294+
.copied()
295+
.map(new_const_name)
296+
.collect();
297+
let ident_inline_const_names: Vec<_> = istrs_for_idents
298+
.iter()
299+
.copied()
300+
.map(new_const_name)
301+
.collect();
267302

268303
// Inline strings
269304
let (inline_const_names, inline_values_and_lengths): (Vec<_>, Vec<_>) = inline_strs
@@ -323,6 +358,12 @@ impl AtomType {
323358
#(
324359
(#inline_strs) => { #module::#inline_const_names };
325360
)*
361+
#(
362+
(#atom_idents) => { #module::#ident_const_names };
363+
)*
364+
#(
365+
(#istr_idents) => { #module::#ident_inline_const_names };
366+
)*
326367
}
327368
}
328369
}
@@ -340,11 +381,13 @@ impl AtomType {
340381
fn test_iteration_order() {
341382
let x1 = crate::AtomType::new("foo::Atom", "foo_atom!")
342383
.atoms(&["x", "xlink", "svg", "test"])
343-
.write_to_string(Vec::new()).expect("write to string cache x1");
384+
.write_to_string(Vec::new())
385+
.expect("write to string cache x1");
344386

345387
let x2 = crate::AtomType::new("foo::Atom", "foo_atom!")
346388
.atoms(&["x", "xlink", "svg", "test"])
347-
.write_to_string(Vec::new()).expect("write to string cache x2");
389+
.write_to_string(Vec::new())
390+
.expect("write to string cache x2");
348391

349392
assert_eq!(x1, x2);
350393
}

0 commit comments

Comments
 (0)