feat(span): introduce format_atom! macro (#10722)

Introduce a `format_atom!` macro. This behaves the same as `std`'s `format!` macro, but constructs the string directly in arena, and returns an `Atom` instead of a `String`.

```rs
let foo_dot_bar: Atom = format_atom!(&allocator, "{}.{}", foo, bar);
```

Can also be used to avoid creating a temp `String` when creating an `Atom` using a `Display` impl:

```rs
// Before
let atom = ctx.ast.atom(&my_display_type.to_string());
// After
let atom = format_atom!(ctx.ast.allocator, "{my_display_type}");
```
This commit is contained in:
overlookmotel committed 2025-05-01 02:03:32 +00:00
1 parent 9ebf3d45d4
commit 0105253cad
2 files changed
+39

No files matched your search

+37
View File
@@ -230,3 +230,40 @@ impl ESTree for Atom<'_> {
ESTree::serialize(self.as_str(), serializer);
}
}
/// Creates an [`Atom`] using interpolation of runtime expressions.
///
/// Identical to [`std`'s `format!` macro](std::format), except:
///
/// * First argument is the allocator.
/// * Produces an [`Atom`] instead of a [`String`].
///
/// The string is built in the arena, without allocating an intermediate `String`.
///
/// # Panics
///
/// Panics if a formatting trait implementation returns an error.
///
/// # Example
///
/// ```
/// use oxc_allocator::Allocator;
/// use oxc_span::format_atom;
/// let allocator = Allocator::new();
///
/// let s1 = "foo";
/// let s2 = "bar";
/// let formatted = format_atom!(&allocator, "{s1}.{s2}");
/// assert_eq!(formatted, "foo.bar");
/// ```
#[macro_export]
macro_rules! format_atom {
($alloc:expr, $($arg:tt)*) => {{
use ::std::{write, fmt::Write};
use $crate::{Atom, __internal::ArenaString};
let mut s = ArenaString::new_in($alloc);
write!(s, $($arg)*).unwrap();
Atom::from(s)
}}
}
+2
View File
@@ -32,4 +32,6 @@ mod generated {
pub mod __internal {
// Used by `format_compact_str!` macro defined in `compact_str.rs`
pub use compact_str::format_compact;
// Used by `format_atom!` macro defined in `atom.rs`
pub use oxc_allocator::String as ArenaString;
}