Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
Merge branch 'refactor/format-and-write-macros' into refactor/binary-…
Browse files Browse the repository at this point in the history
…like-left-to-right
  • Loading branch information
MichaReiser committed Jun 4, 2022
2 parents b81f264 + 2570732 commit bc3effd
Show file tree
Hide file tree
Showing 434 changed files with 2,581 additions and 1,635 deletions.
30 changes: 14 additions & 16 deletions crates/rome_formatter/src/arguments.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{Buffer, Format, Formatter};
use crate::{FormatContext, FormatResult, Formatted};
use crate::FormatResult;
use std::ffi::c_void;
use std::marker::PhantomData;

Expand All @@ -9,7 +9,6 @@ use std::marker::PhantomData;
/// This struct is similar to a dynamic dispatch (using `dyn Format`) because it stores a pointer to the value.
/// However, it doesn't store the pointer to `dyn Format`'s vtable, instead it statically resolves the function
/// pointer of `Format::format` and stores it in `formatter`.
#[derive(Copy, Clone)]
pub struct Argument<'fmt, Context> {
/// The value to format stored as a raw pointer where `lifetime` stores the value's lifetime.
value: *const c_void,
Expand All @@ -21,6 +20,13 @@ pub struct Argument<'fmt, Context> {
formatter: fn(*const c_void, &mut Formatter<'_, Context>) -> FormatResult<()>,
}

impl<Context> Clone for Argument<'_, Context> {
fn clone(&self) -> Self {
*self
}
}
impl<Context> Copy for Argument<'_, Context> {}

impl<'fmt, Context> Argument<'fmt, Context> {
/// Called by the [rome_formatter::format_args] macro. Creates a mono-morphed value for formatting
/// an object.
Expand All @@ -32,7 +38,7 @@ impl<'fmt, Context> Argument<'fmt, Context> {
fmt: &mut Formatter<Context>,
) -> FormatResult<()> {
// SAFETY: Safe because the 'fmt lifetime is captured by the 'lifetime' field.
F::format(unsafe { &*(ptr as *const F) }, fmt)
F::fmt(unsafe { &*(ptr as *const F) }, fmt)
}

Self {
Expand All @@ -41,12 +47,10 @@ impl<'fmt, Context> Argument<'fmt, Context> {
formatter: formatter::<F, Context>,
}
}
}

impl<Context> Format<Context> for Argument<'_, Context> {
/// Formats the value stored by this argument using the given formatter.
#[inline]
fn format(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
pub(super) fn format(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
(self.formatter)(self.value, f)
}
}
Expand Down Expand Up @@ -94,20 +98,14 @@ impl<Context> Clone for Arguments<'_, Context> {

impl<Context> Format<Context> for Arguments<'_, Context> {
#[inline]
fn format(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
fn fmt(&self, formatter: &mut Formatter<Context>) -> FormatResult<()> {
formatter.write_fmt(*self)
}
}

impl<Context> std::fmt::Debug for Arguments<'_, Context>
where
Context: Default + FormatContext,
{
impl<Context> std::fmt::Debug for Arguments<'_, Context> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match crate::format!(Context::default(), [self]) {
Ok(formatted) => Formatted::fmt(&formatted, f),
Err(err) => std::write!(f, "Err({err})"),
}
f.write_str("Arguments[...]")
}
}

Expand All @@ -128,7 +126,7 @@ mod tests {
space_token(),
token("a"),
space_token(),
group_elements(format_args!(token("("), token(")")))
group_elements(&format_args!(token("("), token(")")))
]
)
.unwrap();
Expand Down
74 changes: 67 additions & 7 deletions crates/rome_formatter/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ impl<W: Buffer<Context = Context> + ?Sized, Context> Buffer for &mut W {
}

/// Vector backed [`Buffer`] implementation.
///
/// The buffer writes all elements into the internal elements buffer.
#[derive(Debug)]
pub struct VecBuffer<'a, Context> {
state: &'a mut FormatState<Context>,
Expand All @@ -170,6 +172,7 @@ impl<'a, Context> VecBuffer<'a, Context> {
}
}

/// Creates a buffer with the specified capacity
pub fn with_capacity(capacity: usize, context: &'a mut FormatState<Context>) -> Self {
Self {
state: context,
Expand Down Expand Up @@ -244,15 +247,19 @@ impl<Context> Buffer for VecBuffer<'_, Context> {

fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
let position = snapshot.unwrap_position();
assert!(self.elements.len() >= position);
assert!(
self.elements.len() >= position,
r#"Outdated snapshot. This buffer contains fewer elements than at the time the snapshot was taken.
Make sure that you take and restore the snapshot in order and that this snapshot belongs to the current buffer."#
);

self.elements.truncate(position)
self.elements.truncate(position);
}
}

/// Buffer that writes a pre-amble before the first written content.
/// This struct wraps an existing buffer and emits a preamble text when the first text is written.
///
/// Useful to conditionally write some content.
/// This can be useful if you, for example, want to write some content if what gets written next isn't empty.
///
/// # Examples
///
Expand All @@ -266,7 +273,7 @@ impl<Context> Buffer for VecBuffer<'_, Context> {
/// struct Preamble;
///
/// impl Format<SimpleFormatContext> for Preamble {
/// fn format(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
/// fn fmt(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
/// write!(f, [token("# heading"), hard_line_break()])
/// }
/// }
Expand All @@ -293,7 +300,7 @@ impl<Context> Buffer for VecBuffer<'_, Context> {
/// struct Preamble;
///
/// impl Format<SimpleFormatContext> for Preamble {
/// fn format(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
/// fn fmt(&self, f: &mut Formatter<SimpleFormatContext>) -> FormatResult<()> {
/// write!(f, [token("# heading"), hard_line_break()])
/// }
/// }
Expand All @@ -311,7 +318,7 @@ pub struct PreambleBuffer<'buf, Preamble, Context> {
/// The pre-amble to write once the first content gets written to this buffer.
preamble: Preamble,

/// Whatever some content (including the pre-amble) has been written at this point.
/// Whether some content (including the pre-amble) has been written at this point.
empty: bool,
}

Expand Down Expand Up @@ -372,3 +379,56 @@ struct PreambleBufferSnapshot {
inner: BufferSnapshot,
empty: bool,
}

/// Buffer that allows you inspecting elements as they get written to the formatter.
pub struct Inspect<'inner, Context, Inspector> {
inner: &'inner mut dyn Buffer<Context = Context>,
inspector: Inspector,
}

impl<'inner, Context, Inspector> Inspect<'inner, Context, Inspector> {
pub fn new(inner: &'inner mut dyn Buffer<Context = Context>, inspector: Inspector) -> Self {
Self { inner, inspector }
}
}

impl<'inner, Context, Inspector> Buffer for Inspect<'inner, Context, Inspector>
where
Inspector: FnMut(&FormatElement),
{
type Context = Context;

fn write_element(&mut self, element: FormatElement) -> FormatResult<()> {
(self.inspector)(&element);
self.inner.write_element(element)
}

fn state(&self) -> &FormatState<Self::Context> {
self.inner.state()
}

fn state_mut(&mut self) -> &mut FormatState<Self::Context> {
self.inner.state_mut()
}

fn snapshot(&self) -> BufferSnapshot {
self.inner.snapshot()
}

fn restore_snapshot(&mut self, snapshot: BufferSnapshot) {
self.inner.restore_snapshot(snapshot)
}
}

pub trait BufferExtensions: Buffer + Sized {
/// Returns a new buffer that calls the passed inspector for every element that gets written to the output
#[must_use]
fn inspect<F>(&mut self, inspector: F) -> Inspect<Self::Context, F>
where
F: FnMut(&FormatElement),
{
Inspect::new(self, inspector)
}
}

impl<T> BufferExtensions for T where T: Buffer {}
Loading

0 comments on commit bc3effd

Please sign in to comment.