From 0105253cadca872b38b9827c4d9de452d6293680 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Thu, 1 May 2025 02:03:32 +0000 Subject: [PATCH] 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}"); ``` --- crates/oxc_span/src/atom.rs | 37 +++++++++++++++++++++++++++++++++++++ crates/oxc_span/src/lib.rs | 2 ++ 2 files changed, 39 insertions(+) diff --git a/crates/oxc_span/src/atom.rs b/crates/oxc_span/src/atom.rs index 02cd9bbfabe86..60f31d727b7dd 100644 --- a/crates/oxc_span/src/atom.rs +++ b/crates/oxc_span/src/atom.rs @@ -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) + }} +} diff --git a/crates/oxc_span/src/lib.rs b/crates/oxc_span/src/lib.rs index d8fdbaea95116..02bd38f26977e 100644 --- a/crates/oxc_span/src/lib.rs +++ b/crates/oxc_span/src/lib.rs @@ -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; }