perf(rome_formater): Inline `FormatElement::Text`
MODIFY
crates/rome_formatter/src/arguments.rs
crates/rome_formatter/src/arguments.rs
@@ -145,14 +145,14 @@ mod tests {
assert_eq!(
buffer.into_vec(),
vec![
- FormatElement::Text(Text::Static { text: "function" }),
+ FormatElement::StaticText { text: "function" },
FormatElement::Space,
- FormatElement::Text(Text::Static { text: "a" }),
+ FormatElement::StaticText { text: "a" },
FormatElement::Space,
// Group
FormatElement::Tag(Tag::StartGroup(tag::Group::new())),
- FormatElement::Text(Text::Static { text: "(" }),
- FormatElement::Text(Text::Static { text: ")" }),
+ FormatElement::StaticText { text: "(" },
+ FormatElement::StaticText { text: ")" },
FormatElement::Tag(Tag::EndGroup)
]
);

MODIFY
crates/rome_formatter/src/buffer.rs
crates/rome_formatter/src/buffer.rs
@@ -20,14 +20,14 @@ pub trait Buffer {
/// # Examples
///
/// ```
- /// use rome_formatter::{Buffer, FormatElement, FormatState, SimpleFormatContext, Text, VecBuffer};
+ /// use rome_formatter::{Buffer, FormatElement, FormatState, SimpleFormatContext, VecBuffer};
///
/// let mut state = FormatState::new(SimpleFormatContext::default());
/// let mut buffer = VecBuffer::new(&mut state);
///
- /// buffer.write_element(FormatElement::Text(Text::Static { text: "test"})).unwrap();
+ /// buffer.write_element(FormatElement::StaticText { text: "test"}).unwrap();
///
- /// assert_eq!(buffer.into_vec(), vec![FormatElement::Text(Text::Static { text: "test" })]);
+ /// assert_eq!(buffer.into_vec(), vec![FormatElement::StaticText { text: "test" }]);
/// ```
///
fn write_element(&mut self, element: FormatElement) -> FormatResult<()>;
@@ -46,14 +46,14 @@ pub trait Buffer {
///
/// ```
/// use rome_formatter::prelude::*;
- /// use rome_formatter::{Buffer, FormatState, SimpleFormatContext, Text, VecBuffer, format_args};
+ /// use rome_formatter::{Buffer, FormatState, SimpleFormatContext, VecBuffer, format_args};
///
/// let mut state = FormatState::new(SimpleFormatContext::default());
/// let mut buffer = VecBuffer::new(&mut state);
///
/// buffer.write_fmt(format_args!(text("Hello World"))).unwrap();
///
- /// assert_eq!(buffer.into_vec(), vec![FormatElement::Text(Text::Static { text: "Hello World" })]);
+ /// assert_eq!(buffer.into_vec(), vec![FormatElement::StaticText{ text: "Hello World" }]);
/// ```
fn write_fmt(mut self: &mut Self, arguments: Arguments<Self::Context>) -> FormatResult<()> {
write(&mut self, arguments)
@@ -466,10 +466,10 @@ where
/// assert_eq!(
/// formatted.document().as_ref(),
/// &[
-/// FormatElement::Text(Text::Static { text: "The next soft line or space gets replaced by a space" }),
+/// FormatElement::StaticText { text: "The next soft line or space gets replaced by a space" },
/// FormatElement::Space,
-/// FormatElement::Text(Text::Static { text: "and the line here" }),
-/// FormatElement::Text(Text::Static { text: "is removed entirely." })
+/// FormatElement::StaticText { text: "and the line here" },
+/// FormatElement::StaticText { text: "is removed entirely." }
/// ]
/// );
///
@@ -635,10 +635,10 @@ pub trait BufferExtensions: Buffer + Sized {
/// assert_eq!(
/// recorded.deref(),
/// &[
- /// FormatElement::Text(Text::Static{ text: "A" }),
- /// FormatElement::Text(Text::Static{ text: "B" }),
- /// FormatElement::Text(Text::Static{ text: "C" }),
- /// FormatElement::Text(Text::Static{ text: "D" })
+ /// FormatElement::StaticText{ text: "A" },
+ /// FormatElement::StaticText{ text: "B" },
+ /// FormatElement::StaticText{ text: "C" },
+ /// FormatElement::StaticText{ text: "D" }
/// ]
/// );
///

MODIFY
crates/rome_formatter/src/builders.rs
crates/rome_formatter/src/builders.rs
@@ -265,7 +265,7 @@ pub struct StaticText {
impl<Context> Format<Context> for StaticText {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
- f.write_element(FormatElement::Text(Text::Static { text: self.text }))
+ f.write_element(FormatElement::StaticText { text: self.text })
}
}
@@ -290,10 +290,10 @@ pub struct DynamicText<'a> {
impl<Context> Format<Context> for DynamicText<'_> {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
- f.write_element(FormatElement::Text(Text::Dynamic {
+ f.write_element(FormatElement::DynamicText {
text: self.text.to_string().into_boxed_str(),
source_position: self.position,
- }))
+ })
}
}
@@ -335,15 +335,15 @@ impl<L: Language, Context> Format<Context> for SyntaxTokenCowSlice<'_, L> {
let relative_range = range - self.token.text_range().start();
let slice = self.token.token_text().slice(relative_range);
- f.write_element(FormatElement::Text(Text::SyntaxTokenTextSlice {
+ f.write_element(FormatElement::SyntaxTokenTextSlice {
slice,
source_position: self.start,
- }))
+ })
}
- Cow::Owned(text) => f.write_element(FormatElement::Text(Text::Dynamic {
+ Cow::Owned(text) => f.write_element(FormatElement::DynamicText {
text: text.to_string().into_boxed_str(),
source_position: self.start,
- })),
+ }),
}
}
}
@@ -377,10 +377,10 @@ pub struct SyntaxTokenTextSlice {
impl<Context> Format<Context> for SyntaxTokenTextSlice {
fn fmt(&self, f: &mut Formatter<Context>) -> FormatResult<()> {
- f.write_element(FormatElement::Text(Text::SyntaxTokenTextSlice {
+ f.write_element(FormatElement::SyntaxTokenTextSlice {
slice: self.text.clone(),
source_position: self.source_position,
- }))
+ })
}
}

MODIFY
crates/rome_formatter/src/format_element.rs
crates/rome_formatter/src/format_element.rs
@@ -26,8 +26,26 @@ pub enum FormatElement {
/// Forces the parent group to print in expanded mode.
ExpandParent,
- /// A text that should be printed as is, see [crate::builders::text] for documentation and examples.
- Text(Text),
+ /// Token constructed by the formatter from a static string
+ StaticText { text: &'static str },
+
+ /// Token constructed from the input source as a dynamic
+ /// string with its start position in the input document.
+ DynamicText {
+ /// There's no need for the text to be mutable, using `Box<str>` safes 8 bytes over `String`.
+ text: Box<str>,
+ /// The start position of the dynamic token in the unformatted source code
+ source_position: TextSize,
+ },
+
+ /// A token for a text that is taken as is from the source code (input text and formatted representation are identical).
+ /// Implementing by taking a slice from a `SyntaxToken` to avoid allocating a new string.
+ SyntaxTokenTextSlice {
+ /// The start position of the token in the unformatted source code
+ source_position: TextSize,
+ /// The token text
+ slice: SyntaxTokenText,
+ },
/// Prevents that line suffixes move past this boundary. Forces the printer to print any pending
/// line suffixes, potentially by inserting a hard line break.
@@ -51,7 +69,16 @@ impl std::fmt::Debug for FormatElement {
FormatElement::Space => write!(fmt, "Space"),
FormatElement::Line(mode) => fmt.debug_tuple("Line").field(mode).finish(),
FormatElement::ExpandParent => write!(fmt, "ExpandParent"),
- FormatElement::Text(text) => text.fmt(fmt),
+ FormatElement::StaticText { text } => {
+ fmt.debug_tuple("StaticText").field(text).finish()
+ }
+ FormatElement::DynamicText { text, .. } => {
+ fmt.debug_tuple("DynamicText").field(text).finish()
+ }
+ FormatElement::SyntaxTokenTextSlice { slice, .. } => fmt
+ .debug_tuple("SyntaxTokenTextSlice")
+ .field(slice)
+ .finish(),
FormatElement::LineSuffixBoundary => write!(fmt, "LineSuffixBoundary"),
FormatElement::BestFitting(best_fitting) => {
fmt.debug_tuple("BestFitting").field(&best_fitting).finish()
@@ -140,68 +167,6 @@ impl Deref for Interned {
}
}
-/// See [crate::builders::text] for documentation
-#[derive(Eq, Clone)]
-pub enum Text {
- /// Token constructed by the formatter from a static string
- Static { text: &'static str },
- /// Token constructed from the input source as a dynamics
- /// string and a range of the input source
- Dynamic {
- // There's no need for the text to be mutable, using `Box<str>` safes 8 bytes over `String`.
- text: Box<str>,
- // The position of the dynamic token in the unformatted source code
- source_position: TextSize,
- },
- /// A token for a text that is taken as is from the source code (input text and formatted representation are identical).
- /// Implementing by taking a slice from a `SyntaxToken` to avoid allocating a new string.
- SyntaxTokenTextSlice {
- /// The start position of the token in the unformatted source code
- source_position: TextSize,
- /// The token text
- slice: SyntaxTokenText,
- },
-}
-
-impl std::fmt::Debug for Text {
- fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
- // This does not use debug_tuple so the tokens are
- // written on a single line even when pretty-printing
- match self {
- Text::Static { text } => write!(fmt, "StaticText({:?})", text),
- Text::Dynamic { text, .. } => write!(fmt, "DynamicText({:?})", text),
- Text::SyntaxTokenTextSlice {
- slice: token_text, ..
- } => {
- write!(fmt, "SyntaxTokenTextSlice({:?})", token_text)
- }
- }
- }
-}
-
-impl Text {
- /// Get the range of the input source covered by this token,
- /// or None if the token was synthesized by the formatter
- pub fn source_position(&self) -> Option<&TextSize> {
- match self {
- Text::Static { .. } => None,
- Text::Dynamic {
- source_position, ..
- } => Some(source_position),
- Text::SyntaxTokenTextSlice {
- source_position, ..
- } => Some(source_position),
- }
- }
-}
-
-// Token equality only compares the text content
-impl PartialEq for Text {
- fn eq(&self, other: &Self) -> bool {
- **self == **other
- }
-}
-
const LINE_SEPARATOR: char = '\u{2028}';
const PARAGRAPH_SEPARATOR: char = '\u{2029}';
pub const LINE_TERMINATORS: [char; 3] = ['\r', LINE_SEPARATOR, PARAGRAPH_SEPARATOR];
@@ -234,19 +199,6 @@ pub fn normalize_newlines<const N: usize>(text: &str, terminators: [char; N]) ->
}
}
-impl Deref for Text {
- type Target = str;
- fn deref(&self) -> &Self::Target {
- match self {
- Text::Static { text } => text,
- Text::Dynamic { text, .. } => text,
- Text::SyntaxTokenTextSlice {
- slice: token_text, ..
- } => token_text.deref(),
- }
- }
-}
-
impl FormatElement {
/// Returns `true` if self is a [FormatElement::Tag]
pub const fn is_tag(&self) -> bool {
@@ -268,6 +220,19 @@ impl FormatElement {
_ => false,
}
}
+
+ pub const fn is_text(&self) -> bool {
+ matches!(
+ self,
+ FormatElement::SyntaxTokenTextSlice { .. }
+ | FormatElement::DynamicText { .. }
+ | FormatElement::StaticText { .. }
+ )
+ }
+
+ pub const fn is_space(&self) -> bool {
+ matches!(self, FormatElement::Space)
+ }
}
impl FormatElements for FormatElement {
@@ -276,7 +241,9 @@ impl FormatElements for FormatElement {
FormatElement::ExpandParent => true,
FormatElement::Tag(Tag::StartGroup(group)) => !group.mode().is_flat(),
FormatElement::Line(line_mode) => matches!(line_mode, LineMode::Hard | LineMode::Empty),
- FormatElement::Text(text) => text.contains('\n'),
+ FormatElement::StaticText { text } => text.contains('\n'),
+ FormatElement::DynamicText { text, .. } => text.contains('\n'),
+ FormatElement::SyntaxTokenTextSlice { slice, .. } => slice.contains('\n'),
FormatElement::Interned(interned) => interned.will_break(),
// Traverse into the most flat version because the content is guaranteed to expand when even
// the most flat version contains some content that forces a break.
@@ -307,12 +274,6 @@ impl FormatElements for FormatElement {
}
}
-impl From<Text> for FormatElement {
- fn from(token: Text) -> Self {
- FormatElement::Text(token)
- }
-}
-
/// Provides the printer with different representations for the same element so that the printer
/// can pick the best fitting variant.
///
@@ -420,9 +381,6 @@ static_assert!(std::mem::size_of::<rome_rowan::TextRange>() == 8usize);
#[cfg(target_pointer_width = "64")]
static_assert!(std::mem::size_of::<crate::format_element::tag::VerbatimKind>() == 8usize);
-#[cfg(target_pointer_width = "64")]
-static_assert!(std::mem::size_of::<crate::format_element::Text>() == 24usize);
-
#[cfg(not(debug_assertions))]
#[cfg(target_pointer_width = "64")]
static_assert!(std::mem::size_of::<crate::format_element::Tag>() == 16usize);
@@ -434,4 +392,4 @@ static_assert!(std::mem::size_of::<crate::format_element::Tag>() == 16usize);
#[cfg(not(debug_assertions))]
#[cfg(target_pointer_width = "64")]
-static_assert!(std::mem::size_of::<crate::FormatElement>() == 32usize);
+static_assert!(std::mem::size_of::<crate::FormatElement>() == 24usize);

MODIFY
crates/rome_formatter/src/format_element/document.rs
crates/rome_formatter/src/format_element/document.rs
@@ -79,7 +79,9 @@ impl Document {
enclosing.pop();
continue;
}
- FormatElement::Text(text) => text.contains('\n'),
+ FormatElement::StaticText { text } => text.contains('\n'),
+ FormatElement::DynamicText { text, .. } => text.contains('\n'),
+ FormatElement::SyntaxTokenTextSlice { slice, .. } => slice.contains('\n'),
FormatElement::ExpandParent
| FormatElement::Line(LineMode::Hard | LineMode::Empty) => true,
_ => false,
@@ -189,7 +191,10 @@ impl Format<IrFormatContext> for &[FormatElement] {
first_element = false;
match element {
- element @ FormatElement::Space | element @ FormatElement::Text(_) => {
+ element @ FormatElement::Space
+ | element @ FormatElement::StaticText { .. }
+ | element @ FormatElement::DynamicText { .. }
+ | element @ FormatElement::SyntaxTokenTextSlice { .. } => {
if !in_text {
write!(f, [text("\"")])?;
}
@@ -197,17 +202,14 @@ impl Format<IrFormatContext> for &[FormatElement] {
in_text = true;
match element {
- FormatElement::Text(_) => f.write_element(element.clone())?,
FormatElement::Space => {
write!(f, [text(" ")])?;
}
+ element if element.is_text() => f.write_element(element.clone())?,
_ => unreachable!(),
}
- let is_next_text = matches!(
- iter.peek(),
- Some(FormatElement::Space | FormatElement::Text(_))
- );
+ let is_next_text = iter.peek().map_or(false, |e| e.is_text() || e.is_space());
if !is_next_text {
write!(f, [text("\"")])?;
@@ -677,16 +679,16 @@ mod tests {
use Tag::*;
let document = Document::from(vec![
- FormatElement::Text(Text::Static { text: "[" }),
+ FormatElement::StaticText { text: "[" },
FormatElement::Tag(StartGroup(tag::Group::new())),
FormatElement::Tag(StartIndent),
FormatElement::Line(LineMode::Soft),
- FormatElement::Text(Text::Static { text: "a" }),
+ FormatElement::StaticText { text: "a" },
// Close group instead of indent
FormatElement::Tag(EndGroup),
FormatElement::Line(LineMode::Soft),
FormatElement::Tag(EndIndent),
- FormatElement::Text(Text::Static { text: "]" }),
+ FormatElement::StaticText { text: "]" },
// End tag without start
FormatElement::Tag(EndIndent),
// Start tag without an end

MODIFY
crates/rome_formatter/src/lib.rs
crates/rome_formatter/src/lib.rs
@@ -55,7 +55,7 @@ pub use builders::BestFitting;
use crate::builders::syntax_token_cow_slice;
use crate::comments::{CommentStyle, Comments, SourceComment};
-pub use format_element::{normalize_newlines, FormatElement, Text, LINE_TERMINATORS};
+pub use format_element::{normalize_newlines, FormatElement, LINE_TERMINATORS};
pub use group_id::GroupId;
use rome_rowan::{
Language, SyntaxElement, SyntaxError, SyntaxNode, SyntaxResult, SyntaxToken, SyntaxTriviaPiece,

MODIFY
crates/rome_formatter/src/macros.rs
crates/rome_formatter/src/macros.rs
@@ -58,9 +58,9 @@ macro_rules! format_args {
/// assert_eq!(
/// buffer.into_vec(),
/// vec![
-/// FormatElement::Text(Text::Static { text: "Hello" }),
+/// FormatElement::StaticText { text: "Hello" },
/// FormatElement::Space,
-/// FormatElement::Text(Text::Static { text: "World" }),
+/// FormatElement::StaticText { text: "World" },
/// ]
/// );
/// # Ok(())
@@ -89,7 +89,7 @@ macro_rules! write {
/// dbg_write!(buffer, [text("Hello")])?;
/// // ^-- prints: [src/main.rs:7][0] = StaticToken("Hello")
///
-/// assert_eq!(buffer.into_vec(), vec![FormatElement::Text(Text::Static { text: "Hello" })]);
+/// assert_eq!(buffer.into_vec(), vec![FormatElement::StaticText { text: "Hello" }]);
/// # Ok(())
/// # }
/// ```
@@ -131,9 +131,9 @@ macro_rules! dbg_write {
/// assert_eq!(
/// formatted.into_document(),
/// Document::from(vec![
-/// FormatElement::Text(Text::Static { text: "(" }),
-/// FormatElement::Text(Text::Static { text: "a" }),
-/// FormatElement::Text(Text::Static { text: ")" }),
+/// FormatElement::StaticText { text: "(" },
+/// FormatElement::StaticText { text: "a" },
+/// FormatElement::StaticText { text: ")" },
/// ])
/// );
/// ```
@@ -357,7 +357,7 @@ mod tests {
assert_eq!(
buffer.into_vec(),
- vec![FormatElement::Text(Text::Static { text: "test" })]
+ vec![FormatElement::StaticText { text: "test" }]
);
}
@@ -375,11 +375,11 @@ mod tests {
assert_eq!(
buffer.into_vec(),
vec![
- FormatElement::Text(Text::Static { text: "a" }),
+ FormatElement::StaticText { text: "a" },
FormatElement::Space,
- FormatElement::Text(Text::Static { text: "simple" }),
+ FormatElement::StaticText { text: "simple" },
FormatElement::Space,
- FormatElement::Text(Text::Static { text: "test" })
+ FormatElement::StaticText { text: "test" }
]
);
}

MODIFY
crates/rome_formatter/src/printer/mod.rs
crates/rome_formatter/src/printer/mod.rs
@@ -94,64 +94,15 @@ impl<'a> Printer<'a> {
}
}
- FormatElement::Text(token) => {
- if !self.state.pending_indent.is_empty() {
- let (indent_char, repeat_count) = match self.options.indent_style() {
- IndentStyle::Tab => ('\t', 1),
- IndentStyle::Space(count) => (' ', count),
- };
-
- let indent = std::mem::take(&mut self.state.pending_indent);
- let total_indent_char_count = indent.level() as usize * repeat_count as usize;
-
- self.state
- .buffer
- .reserve(total_indent_char_count + indent.align() as usize);
-
- for _ in 0..total_indent_char_count {
- self.print_char(indent_char);
- }
-
- for _ in 0..indent.align() {
- self.print_char(' ');
- }
- }
-
- // Print pending spaces
- if self.state.pending_space {
- self.print_str(" ");
- self.state.pending_space = false;
- }
-
- // Insert source map markers before and after the token
- //
- // If the token has source position information the start marker
- // will use the start position of the original token, and the end
- // marker will use that position + the text length of the token
- //
- // If the token has no source position (was created by the formatter)
- // both the start and end marker will use the last known position
- // in the input source (from state.source_position)
- if let Some(source) = token.source_position() {
- self.state.source_position = *source;
- }
-
- self.push_marker(SourceMarker {
- source: self.state.source_position,
- dest: self.state.buffer.text_len(),
- });
-
- self.print_str(token);
-
- if token.source_position().is_some() {
- self.state.source_position += TextSize::of(&**token);
- }
-
- self.push_marker(SourceMarker {
- source: self.state.source_position,
- dest: self.state.buffer.text_len(),
- });
- }
+ FormatElement::StaticText { text } => self.print_text(text, None),
+ FormatElement::DynamicText {
+ text,
+ source_position,
+ } => self.print_text(text, Some(*source_position)),
+ FormatElement::SyntaxTokenTextSlice {
+ slice,
+ source_position,
+ } => self.print_text(slice, Some(*source_position)),
FormatElement::Line(line_mode) => {
if args.mode().is_flat()
@@ -327,6 +278,65 @@ impl<'a> Printer<'a> {
result
}
+ fn print_text(&mut self, text: &str, source_position: Option<TextSize>) {
+ if !self.state.pending_indent.is_empty() {
+ let (indent_char, repeat_count) = match self.options.indent_style() {
+ IndentStyle::Tab => ('\t', 1),
+ IndentStyle::Space(count) => (' ', count),
+ };
+
+ let indent = std::mem::take(&mut self.state.pending_indent);
+ let total_indent_char_count = indent.level() as usize * repeat_count as usize;
+
+ self.state
+ .buffer
+ .reserve(total_indent_char_count + indent.align() as usize);
+
+ for _ in 0..total_indent_char_count {
+ self.print_char(indent_char);
+ }
+
+ for _ in 0..indent.align() {
+ self.print_char(' ');
+ }
+ }
+
+ // Print pending spaces
+ if self.state.pending_space {
+ self.print_str(" ");
+ self.state.pending_space = false;
+ }
+
+ // Insert source map markers before and after the token
+ //
+ // If the token has source position information the start marker
+ // will use the start position of the original token, and the end
+ // marker will use that position + the text length of the token
+ //
+ // If the token has no source position (was created by the formatter)
+ // both the start and end marker will use the last known position
+ // in the input source (from state.source_position)
+ if let Some(source) = source_position {
+ self.state.source_position = source;
+ }
+
+ self.push_marker(SourceMarker {
+ source: self.state.source_position,
+ dest: self.state.buffer.text_len(),
+ });
+
+ self.print_str(text);
+
+ if source_position.is_some() {
+ self.state.source_position += text.text_len();
+ }
+
+ self.push_marker(SourceMarker {
+ source: self.state.source_position,
+ dest: self.state.buffer.text_len(),
+ });
+ }
+
fn push_marker(&mut self, marker: SourceMarker) {
if let Some(last) = self.state.source_markers.last() {
if last != &marker {
@@ -989,37 +999,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
}
}
- FormatElement::Text(token) => {
- let indent = std::mem::take(&mut self.state.pending_indent);
- self.state.line_width += indent.level() as usize
- * self.options().indent_width() as usize
- + indent.align() as usize;
-
- if self.state.pending_space {
- self.state.line_width += 1;
- }
-
- for c in token.chars() {
- let char_width = match c {
- '\t' => self.options().tab_width as usize,
- '\n' => {
- return Ok(if self.must_be_flat {
- Fits::No
- } else {
- Fits::Yes
- });
- }
- c => c.width().unwrap_or(0),
- };
- self.state.line_width += char_width;
- }
-
- if self.state.line_width > self.options().print_width.into() {
- return Ok(Fits::No);
- }
-
- self.state.pending_space = false;
- }
+ FormatElement::StaticText { text } => return Ok(self.fits_text(text)),
+ FormatElement::DynamicText { text, .. } => return Ok(self.fits_text(text)),
+ FormatElement::SyntaxTokenTextSlice { slice, .. } => return Ok(self.fits_text(slice)),
FormatElement::LineSuffixBoundary => {
if self.state.has_line_suffix {
@@ -1155,6 +1137,39 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
Ok(Fits::Maybe)
}
+ fn fits_text(&mut self, text: &str) -> Fits {
+ let indent = std::mem::take(&mut self.state.pending_indent);
+ self.state.line_width += indent.level() as usize * self.options().indent_width() as usize
+ + indent.align() as usize;
+
+ if self.state.pending_space {
+ self.state.line_width += 1;
+ }
+
+ for c in text.chars() {
+ let char_width = match c {
+ '\t' => self.options().tab_width as usize,
+ '\n' => {
+ return if self.must_be_flat {
+ Fits::No
+ } else {
+ Fits::Yes
+ };
+ }
+ c => c.width().unwrap_or(0),
+ };
+ self.state.line_width += char_width;
+ }
+
+ if self.state.line_width > self.options().print_width.into() {
+ return Fits::No;
+ }
+
+ self.state.pending_space = false;
+
+ Fits::Maybe
+ }
+
fn finish(mut self) {
self.bomb.defuse();

MODIFY
crates/rome_formatter/src/source_map.rs
crates/rome_formatter/src/source_map.rs
@@ -206,8 +206,9 @@ impl TransformSourceMap {
/// in the original, untransformed source code.
///
/// The printer creates a source map that allows mapping positions from the newly formatted document
- /// back to the locations of the tree. However, the source positions stored in [crate::FormatElement::Text]
- /// are relative to the transformed tree and not the original tree passed to [crate::format_node].
+ /// back to the locations of the tree. However, the source positions stored in [crate::FormatElement::DynamicText]
+ /// and [crate::FormatElement::SyntaxTokenTextSlice] are relative to the transformed tree
+ /// and not the original tree passed to [crate::format_node].
///
/// This function re-maps the positions from the positions in the transformed tree back to the positions
/// in the original, untransformed tree.

MODIFY
crates/rome_js_formatter/src/utils/jsx.rs
crates/rome_js_formatter/src/utils/jsx.rs
@@ -418,10 +418,10 @@ impl JsxWord {
impl Format<JsFormatContext> for JsxWord {
fn fmt(&self, f: &mut Formatter<JsFormatContext>) -> FormatResult<()> {
- f.write_element(FormatElement::Text(Text::SyntaxTokenTextSlice {
+ f.write_element(FormatElement::SyntaxTokenTextSlice {
source_position: self.source_position,
slice: self.text.clone(),
- }))
+ })
}
}

perf(rome_formater): Inline `FormatElement::Text` (#3403)

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>