feat(rome_formatter): Measure unicode width
MODIFY
Cargo.lock
Cargo.lock
@@ -1623,6 +1623,7 @@ dependencies = [
"schemars",
"serde",
"tracing",
+ "unicode-width",
]
[[package]]

MODIFY
crates/rome_diagnostics/src/v2/display/frame.rs
crates/rome_diagnostics/src/v2/display/frame.rs
@@ -7,7 +7,7 @@ use std::{
};
use rome_console::{fmt, markup};
-use rome_text_size::{TextRange, TextSize};
+use rome_text_size::{TextLen, TextRange, TextSize};
use unicode_width::UnicodeWidthChar;
use crate::v2::{
@@ -173,31 +173,31 @@ pub(super) fn print_frame(fmt: &mut fmt::Formatter<'_>, location: Location<'_>)
let is_first_line = line_index == start_location.line_number;
let is_last_line = line_index == end_location.line_number;
+ let start_index_relative_to_line =
+ start_index.max(line_range.start()) - line_range.start();
+ let end_index_relative_to_line = end_index.min(line_range.end()) - line_range.start();
+
let marker = if is_first_line && is_last_line {
// Only line in the selection
- let start_index =
- TextSize::try_from(start_location.column_number.to_zero_indexed())
- .expect("integer overflow");
- let end_index = TextSize::try_from(end_location.column_number.to_zero_indexed())
- .expect("integer overflow");
- Some(TextRange::new(start_index, end_index))
+ Some(TextRange::new(
+ start_index_relative_to_line,
+ end_index_relative_to_line,
+ ))
} else if is_first_line {
// First line in selection
- let start_index =
- TextSize::try_from(start_location.column_number.to_zero_indexed())
- .expect("integer overflow");
- let end_index = TextSize::of(line_text);
- Some(TextRange::new(start_index, end_index))
+ Some(TextRange::new(
+ start_index_relative_to_line,
+ line_text.text_len(),
+ ))
} else if is_last_line {
// Last line in selection
- let start_index = TextSize::of(line_text)
- .checked_sub(TextSize::of(line_text.trim_start()))
+ let start_index = line_text
+ .text_len()
+ .checked_sub(line_text.trim_start().text_len())
// SAFETY: The length of `line_text.trim_start()` should
// never be larger than `line_text` itself
.expect("integer overflow");
- let end_index = TextSize::try_from(end_location.column_number.to_zero_indexed())
- .expect("integer overflow");
- Some(TextRange::new(start_index, end_index))
+ Some(TextRange::new(start_index, end_index_relative_to_line))
} else {
None
};
@@ -440,7 +440,7 @@ impl<'diagnostic> SourceFile<'diagnostic> {
.get(line_index)
.cloned()
.expect("failed despite previous check")),
- Ordering::Equal => Ok(TextSize::of(self.source)),
+ Ordering::Equal => Ok(self.source.text_len()),
Ordering::Greater => Err(io::Error::new(
io::ErrorKind::InvalidInput,
"overflow error",
@@ -495,7 +495,7 @@ impl<'diagnostic> SourceFile<'diagnostic> {
fn column_index(source: &str, line_range: TextRange, byte_index: TextSize) -> usize {
let end_index = std::cmp::min(
byte_index,
- std::cmp::min(line_range.end(), TextSize::of(source)),
+ std::cmp::min(line_range.end(), source.text_len()),
);
(usize::from(line_range.start())..usize::from(end_index))

MODIFY
crates/rome_formatter/Cargo.toml
crates/rome_formatter/Cargo.toml
@@ -18,6 +18,7 @@ rustc-hash = { workspace = true }
countme = { workspace = true }
drop_bomb = "0.1.5"
indexmap = { workspace = true }
+unicode-width = "0.1.9"
[dev-dependencies]
rome_js_parser = { path = "../rome_js_parser"}

MODIFY
crates/rome_formatter/src/printer/mod.rs
crates/rome_formatter/src/printer/mod.rs
@@ -26,6 +26,7 @@ use crate::printer::queue::{
use drop_bomb::DebugDropBomb;
use rome_rowan::{TextLen, TextSize};
use std::num::NonZeroU8;
+use unicode_width::UnicodeWidthChar;
/// Prints the format elements into a string
#[derive(Debug, Default)]
@@ -657,7 +658,7 @@ impl<'a> Printer<'a> {
let char_width = if char == '\t' {
self.options.tab_width as usize
} else {
- 1
+ char.width().unwrap_or(0)
};
self.state.line_width += char_width;
@@ -1000,7 +1001,7 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
for c in token.chars() {
let char_width = match c {
- '\t' => self.options().tab_width,
+ '\t' => self.options().tab_width as usize,
'\n' => {
return Ok(if self.must_be_flat {
Fits::No
@@ -1008,9 +1009,9 @@ impl<'a, 'print> FitsMeasurer<'a, 'print> {
Fits::Yes
});
}
- _ => 1,
+ c => c.width().unwrap_or(0),
};
- self.state.line_width += char_width as usize;
+ self.state.line_width += char_width;
}
if self.state.line_width > self.options().print_width.into() {

feat(rome_formatter): Measure unicode width (#3383)