feat(rome_js_formatter): number literals, number literal types, bigint literal types
MODIFY
crates/rome_js_formatter/src/js/expressions/number_literal_expression.rs
crates/rome_js_formatter/src/js/expressions/number_literal_expression.rs
use crate::prelude::*;
+use crate::utils::number_utils::CleanedNumberLiteralText;
use crate::parentheses::{is_member_object, NeedsParentheses};
-use rome_formatter::write;
use rome_js_syntax::JsNumberLiteralExpression;
use rome_js_syntax::{JsNumberLiteralExpressionFields, JsSyntaxNode};
@@ -15,9 +15,7 @@ impl FormatNodeRule<JsNumberLiteralExpression> for FormatJsNumberLiteralExpressi
f: &mut JsFormatter,
) -> FormatResult<()> {
let JsNumberLiteralExpressionFields { value_token } = node.as_fields();
- let value_token = value_token?;
-
- write![f, [value_token.format()]]
+ CleanedNumberLiteralText::from_number_literal_token(&value_token?).fmt(f)
}
fn needs_parentheses(&self, item: &JsNumberLiteralExpression) -> bool {

MODIFY
crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs
crates/rome_js_formatter/src/ts/types/big_int_literal_type.rs
+use std::borrow::Cow;
+
use crate::prelude::*;
use crate::parentheses::NeedsParentheses;
+use crate::utils::string_utils::ToAsciiLowercaseCow;
use rome_formatter::write;
use rome_js_syntax::{JsSyntaxNode, TsBigIntLiteralType, TsBigIntLiteralTypeFields};
@@ -13,8 +16,22 @@ impl FormatNodeRule<TsBigIntLiteralType> for FormatTsBigIntLiteralType {
minus_token,
literal_token,
} = node.as_fields();
+ write![f, [minus_token.format()]]?;
+ let literal_token = literal_token?;
- write![f, [minus_token.format(), literal_token.format()]]
+ let original = literal_token.text_trimmed();
+ match original.to_ascii_lowercase_cow() {
+ Cow::Borrowed(_) => write![f, [literal_token.format()]],
+ Cow::Owned(lowercase) => {
+ write!(
+ f,
+ [format_replaced(
+ &literal_token,
+ &dynamic_text(&lowercase, literal_token.text_trimmed_range().start())
+ )]
+ )
+ }
+ }
}
fn needs_parentheses(&self, item: &TsBigIntLiteralType) -> bool {

MODIFY
crates/rome_js_formatter/src/ts/types/number_literal_type.rs
crates/rome_js_formatter/src/ts/types/number_literal_type.rs
use crate::prelude::*;
use crate::parentheses::NeedsParentheses;
+use crate::utils::number_utils::CleanedNumberLiteralText;
use rome_formatter::write;
use rome_js_syntax::{JsSyntaxNode, TsNumberLiteralType, TsNumberLiteralTypeFields};
@@ -13,7 +14,13 @@ impl FormatNodeRule<TsNumberLiteralType> for FormatTsNumberLiteralType {
minus_token,
literal_token,
} = node.as_fields();
- write![f, [minus_token.format(), literal_token.format()]]
+ write![
+ f,
+ [
+ minus_token.format(),
+ CleanedNumberLiteralText::from_number_literal_token(&literal_token?)
+ ]
+ ]
}
fn needs_parentheses(&self, item: &TsNumberLiteralType) -> bool {

MODIFY
crates/rome_js_formatter/src/utils/mod.rs
crates/rome_js_formatter/src/utils/mod.rs
@@ -2,6 +2,7 @@ pub(crate) mod array;
mod assignment_like;
mod binary_like_expression;
mod conditional;
+pub mod number_utils;
pub mod string_utils;
pub(crate) mod format_class;

ADD
crates/rome_js_formatter/src/utils/number_utils.rs
+use crate::prelude::*;
+use crate::utils::string_utils::ToAsciiLowercaseCow;
+use crate::JsFormatContext;
+use crate::JsFormatter;
+use rome_formatter::trivia::format_replaced;
+use rome_formatter::Format;
+use rome_formatter::FormatResult;
+use rome_js_syntax::JsSyntaxKind::JS_NUMBER_LITERAL;
+use rome_js_syntax::JsSyntaxKind::TS_NUMBER_LITERAL_TYPE;
+use rome_js_syntax::JsSyntaxToken;
+use std::borrow::Cow;
+use std::num::NonZeroUsize;
+
+pub struct CleanedNumberLiteralText<'token> {
+ token: &'token JsSyntaxToken,
+ text: Cow<'token, str>,
+}
+
+impl Format<JsFormatContext> for CleanedNumberLiteralText<'_> {
+ fn fmt(&self, f: &mut JsFormatter) -> FormatResult<()> {
+ format_replaced(
+ self.token,
+ &syntax_token_cow_slice(
+ self.text.clone(),
+ self.token,
+ self.token.text_trimmed_range().start(),
+ ),
+ )
+ .fmt(f)
+ }
+}
+
+impl<'token> CleanedNumberLiteralText<'token> {
+ pub fn from_number_literal_token(token: &'token JsSyntaxToken) -> Self {
+ debug_assert!(matches!(
+ &token.kind(),
+ JS_NUMBER_LITERAL | TS_NUMBER_LITERAL_TYPE
+ ));
+ CleanedNumberLiteralText {
+ token,
+ text: format_trimmed_number(token.text_trimmed()),
+ }
+ }
+}
+
+enum FormatNumberLiteralState {
+ IntegerPart,
+ DecimalPart(FormatNumberLiteralDecimalPart),
+ Exponent(FormatNumberLiteralExponent),
+}
+use FormatNumberLiteralState::*;
+struct FormatNumberLiteralDecimalPart {
+ dot_index: usize,
+ last_non_zero_index: Option<NonZeroUsize>,
+}
+struct FormatNumberLiteralExponent {
+ e_index: usize,
+ is_negative: bool,
+ first_digit_index: Option<NonZeroUsize>,
+ first_non_zero_index: Option<NonZeroUsize>,
+}
+// Regex-free version of https://github.com/prettier/prettier/blob/ca246afacee8e6d5db508dae01730c9523bbff1d/src/common/util.js#L341-L356
+fn format_trimmed_number(text: &str) -> Cow<str> {
+ let text = text.to_ascii_lowercase_cow();
+ let mut copied_or_ignored_chars = 0usize;
+ let mut iter = text.chars().enumerate();
+ let mut curr = iter.next();
+ let mut state = IntegerPart;
+
+ // Will be filled only if and when the first place that needs reformatting is detected.
+ let mut cleaned_text = String::new();
+
+ // Look at only the start of the text, ignore any sign, and make sure numbers always start with a digit. Add 0 if missing.
+ if let Some((_, '+' | '-')) = curr {
+ curr = iter.next();
+ }
+ if let Some((curr_index, '.')) = curr {
+ cleaned_text.push_str(&text[copied_or_ignored_chars..curr_index]);
+ copied_or_ignored_chars = curr_index;
+ cleaned_text.push('0');
+ }
+
+ // Loop over the rest of the text, applying the remaining rules.
+ loop {
+ // We use a None pseudo-char at the end of the string to simplify the match cases that follow
+ let curr_or_none_terminator_char = match curr {
+ Some((curr_index, curr_char)) => (curr_index, Some(curr_char)),
+ None => (text.len(), None),
+ };
+ // Look for termination of the decimal part or exponent and see if we need to print it differently.
+ match (&state, curr_or_none_terminator_char) {
+ (
+ DecimalPart(FormatNumberLiteralDecimalPart {
+ dot_index,
+ last_non_zero_index: None,
+ }),
+ (curr_index, Some('e') | None),
+ ) => {
+ // The decimal part equals zero, ignore it completely.
+ // Caveat: Prettier still prints a single `.0` unless there was *only* a trailing dot.
+ if curr_index > dot_index + 1 {
+ cleaned_text.push_str(&text[copied_or_ignored_chars..=*dot_index]);
+ cleaned_text.push('0');
+ } else {
+ cleaned_text.push_str(&text[copied_or_ignored_chars..*dot_index]);
+ }
+ copied_or_ignored_chars = curr_index;
+ }
+ (
+ DecimalPart(FormatNumberLiteralDecimalPart {
+ last_non_zero_index: Some(last_non_zero_index),
+ ..
+ }),
+ (curr_index, Some('e') | None),
+ ) if last_non_zero_index.get() < curr_index - 1 => {
+ // The decimal part ends with at least one zero, ignore them but copy the part from the dot until the last non-zero.
+ cleaned_text.push_str(&text[copied_or_ignored_chars..=last_non_zero_index.get()]);
+ copied_or_ignored_chars = curr_index;
+ }
+ (
+ Exponent(FormatNumberLiteralExponent {
+ e_index,
+ first_non_zero_index: None,
+ ..
+ }),
+ (curr_index, None),
+ ) => {
+ // The exponent equals zero, ignore it completely.
+ cleaned_text.push_str(&text[copied_or_ignored_chars..*e_index]);
+ copied_or_ignored_chars = curr_index;
+ }
+ (
+ Exponent(FormatNumberLiteralExponent {
+ e_index,
+ is_negative,
+ first_digit_index: Some(first_digit_index),
+ first_non_zero_index: Some(first_non_zero_index),
+ }),
+ (curr_index, None),
+ ) if (first_digit_index.get() > e_index + 1 && !is_negative)
+ || (first_non_zero_index.get() > first_digit_index.get()) =>
+ {
+ // The exponent begins with a plus or at least one zero, ignore them but copy the part from the first non-zero until the end.
+ cleaned_text.push_str(&text[copied_or_ignored_chars..=*e_index]);
+ if *is_negative {
+ cleaned_text.push('-');
+ }
+ cleaned_text.push_str(&text[first_non_zero_index.get()..curr_index]);
+ copied_or_ignored_chars = curr_index;
+ }
+ _ => {}
+ }
+
+ // Update state after the current char
+ match (&state, curr) {
+ // Cases entering or remaining in decimal part
+ (_, Some((curr_index, '.'))) => {
+ state = DecimalPart(FormatNumberLiteralDecimalPart {
+ dot_index: curr_index,
+ last_non_zero_index: None,
+ });
+ }
+ (DecimalPart(decimal_part), Some((curr_index, '1'..='9'))) => {
+ state = DecimalPart(FormatNumberLiteralDecimalPart {
+ last_non_zero_index: Some(unsafe {
+ // We've already entered InDecimalPart, so curr_index must be >0
+ NonZeroUsize::new_unchecked(curr_index)
+ }),
+ ..*decimal_part
+ });
+ }
+ // Cases entering or remaining in exponent
+ (_, Some((curr_index, 'e'))) => {
+ state = Exponent(FormatNumberLiteralExponent {
+ e_index: curr_index,
+ is_negative: false,
+ first_digit_index: None,
+ first_non_zero_index: None,
+ });
+ }
+ (Exponent(exponent), Some((_, '-'))) => {
+ state = Exponent(FormatNumberLiteralExponent {
+ is_negative: true,
+ ..*exponent
+ });
+ }
+ (
+ Exponent(
+ exponent @ FormatNumberLiteralExponent {
+ first_digit_index: None,
+ ..
+ },
+ ),
+ Some((curr_index, curr_char @ '0'..='9')),
+ ) => {
+ state = Exponent(FormatNumberLiteralExponent {
+ first_digit_index: Some(unsafe {
+ // We've already entered InExponent, so curr_index must be >0
+ NonZeroUsize::new_unchecked(curr_index)
+ }),
+ first_non_zero_index: if curr_char != '0' {
+ Some(unsafe {
+ // We've already entered InExponent, so curr_index must be >0
+ NonZeroUsize::new_unchecked(curr_index)
+ })
+ } else {
+ None
+ },
+ ..*exponent
+ });
+ }
+ (
+ Exponent(
+ exponent @ FormatNumberLiteralExponent {
+ first_non_zero_index: None,
+ ..
+ },
+ ),
+ Some((curr_index, '1'..='9')),
+ ) => {
+ state = Exponent(FormatNumberLiteralExponent {
+ first_non_zero_index: Some(unsafe { NonZeroUsize::new_unchecked(curr_index) }),
+ ..*exponent
+ });
+ }
+ _ => {}
+ }
+
+ // Repeat or exit
+ match curr {
+ None | Some((_, 'x') /* hex bailout */) => break,
+ Some(_) => curr = iter.next(),
+ }
+ }
+
+ if cleaned_text.is_empty() {
+ text
+ } else {
+ // Append any unconsidered text
+ cleaned_text.push_str(&text[copied_or_ignored_chars..]);
+ Cow::Owned(cleaned_text)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::borrow::Cow;
+
+ use super::format_trimmed_number;
+
+ #[test]
+ fn removes_unnecessary_plus_and_zeros_from_scientific_notation() {
+ assert_eq!("1e2", format_trimmed_number("1e02"));
+ assert_eq!("1e2", format_trimmed_number("1e+2"));
+ }
+
+ #[test]
+ fn removes_unnecessary_scientific_notation() {
+ assert_eq!("1", format_trimmed_number("1e0"));
+ assert_eq!("1", format_trimmed_number("1e-0"));
+ }
+ #[test]
+ fn does_not_get_bamboozled_by_hex() {
+ assert_eq!("0xe0", format_trimmed_number("0xe0"));
+ assert_eq!("0x10e0", format_trimmed_number("0x10e0"));
+ }
+
+ #[test]
+ fn makes_sure_numbers_always_start_with_a_digit() {
+ assert_eq!("0.2", format_trimmed_number(".2"));
+ }
+
+ #[test]
+ fn removes_extraneous_trailing_decimal_zeroes() {
+ assert_eq!("0.1", format_trimmed_number("0.10"));
+ }
+ #[test]
+ fn keeps_one_trailing_decimal_zero() {
+ assert_eq!("0.0", format_trimmed_number("0.00"));
+ }
+
+ #[test]
+ fn removes_trailing_dot() {
+ assert_eq!("1", format_trimmed_number("1."));
+ }
+
+ #[test]
+ fn cleans_all_at_once() {
+ assert_eq!("0.0", format_trimmed_number(".00e-0"));
+ }
+
+ #[test]
+ fn keeps_the_input_string_if_no_change_needed() {
+ assert!(matches!(
+ format_trimmed_number("0.1e2"),
+ Cow::Borrowed("0.1e2")
+ ));
+ }
+}

DELETE
crates/rome_js_formatter/tests/specs/prettier/js/literal-numeric-separator/test.js.snap
----
-source: crates/rome_js_formatter/tests/prettier_tests.rs
----
-
-# Input
-
-```js
-1_1
-1_1.1_1
-0o1_1
-0o0_11
-1.1_0_1e1
-1.1_0_1E1
-.1_1
-0x1_1
-0xa_1
-0xA_1
-0b01_1
-0b0_1_1
-```
-
-
-# Prettier differences
-
-```diff
---- Prettier
-+++ Rome
-@@ -3,10 +3,10 @@
- 0o1_1;
- 0o0_11;
- 1.1_0_1e1;
--1.1_0_1e1;
--0.1_1;
-+1.1_0_1E1;
-+.1_1;
- 0x1_1;
--0xa_1;
- 0xa_1;
-+0xA_1;
- 0b01_1;
- 0b0_1_1;
-```
-
-# Output
-
-```js
-1_1;
-1_1.1_1;
-0o1_1;
-0o0_11;
-1.1_0_1e1;
-1.1_0_1E1;
-.1_1;
-0x1_1;
-0xa_1;
-0xA_1;
-0b01_1;
-0b0_1_1;
-```
-
-
-

DELETE
crates/rome_js_formatter/tests/specs/prettier/js/literal/number.js.snap
----
-source: crates/rome_js_formatter/tests/prettier_tests.rs
----
-
-# Input
-
-```js
-// parentheses around numeric literal should be preserved
-function test5() {
- return (100).toString();
-}
-
-0
-1
-
-0.1
-1.1
-
-.1
-1.
-
-0b1
-0B1
-0o1
-0O1
-0x1
-0X1
-
-0x123abcdef456ABCDEF
-0X123abcdef456ABCDEF
-0xdeadbeef;
-
-0b111000
-0b000111
-0B111000
-0B000111
-0o111000
-0o000111
-0O111000
-0O000111
-0x111000
-0x000111
-0X111000
-0X000111
-
-1e1
-1e+1
-1e-1
-1.e1
-.1e1
-1.1e1
-1.1e0010
-.1e+0010
-.1e-0010
-
-1E1
-1E+1
-1E-1
-1.E1
-.1E1
-1.1E1
-1.1E0010
-.1E+0010
-.1E-0010
-
-0.5e0
-0.5e00
-0.5e+0
-0.5e+00
-0.5e-0
-0.5e-00
-
-1
-1.00500
-1.0
-1.5
-1.50
-0
-0.00500
-0.0
-0.0000
-.0
-500600.001230045000
-1.00500e60
-1.0e60
-0.00500e60
-0.0e60
-0.0000e60
-.0e60
-0.e60
-0e60
-500600.001230045000e60
-10
-9700
-10e100
-```
-
-
-# Prettier differences
-
-```diff
---- Prettier
-+++ Rome
-@@ -9,80 +9,80 @@
- 0.1;
- 1.1;
-
--0.1;
--1;
-+.1;
-+1.;
-
--0b1;
- 0b1;
-+0B1;
- 0o1;
--0o1;
-+0O1;
- 0x1;
--0x1;
-+0X1;
-
--0x123abcdef456abcdef;
--0x123abcdef456abcdef;
-+0x123abcdef456ABCDEF;
-+0X123abcdef456ABCDEF;
- 0xdeadbeef;
-
--0b111000;
--0b000111;
- 0b111000;
- 0b000111;
--0o111000;
--0o000111;
-+0B111000;
-+0B000111;
- 0o111000;
- 0o000111;
-+0O111000;
-+0O000111;
- 0x111000;
- 0x000111;
--0x111000;
--0x000111;
-+0X111000;
-+0X000111;
-
- 1e1;
--1e1;
-+1e+1;
- 1e-1;
--1e1;
--0.1e1;
-+1.e1;
-+.1e1;
- 1.1e1;
--1.1e10;
--0.1e10;
--0.1e-10;
-+1.1e0010;
-+.1e+0010;
-+.1e-0010;
-
--1e1;
--1e1;
--1e-1;
--1e1;
--0.1e1;
--1.1e1;
--1.1e10;
--0.1e10;
--0.1e-10;
-+1E1;
-+1E+1;
-+1E-1;
-+1.E1;
-+.1E1;
-+1.1E1;
-+1.1E0010;
-+.1E+0010;
-+.1E-0010;
-
--0.5;
--0.5;
--0.5;
--0.5;
--0.5;
--0.5;
-+0.5e0;
-+0.5e00;
-+0.5e+0;
-+0.5e+00;
-+0.5e-0;
-+0.5e-00;
-
- 1;
--1.005;
-+1.00500;
- 1.0;
--1.5;
- 1.5;
-+1.50;
- 0;
--0.005;
-+0.00500;
- 0.0;
--0.0;
--0.0;
--500600.001230045;
--1.005e60;
-+0.0000;
-+.0;
-+500600.001230045000;
-+1.00500e60;
- 1.0e60;
--0.005e60;
-+0.00500e60;
- 0.0e60;
--0.0e60;
--0.0e60;
--0e60;
-+0.0000e60;
-+.0e60;
-+0.e60;
- 0e60;
--500600.001230045e60;
-+500600.001230045000e60;
- 10;
- 9700;
- 10e100;
-```
-
-# Output
-
-```js
-// parentheses around numeric literal should be preserved
-function test5() {
- return (100).toString();
-}
-
-0;
-1;
-
-0.1;
-1.1;
-
-.1;
-1.;
-
-0b1;
-0B1;
-0o1;
-0O1;
-0x1;
-0X1;
-
-0x123abcdef456ABCDEF;
-0X123abcdef456ABCDEF;
-0xdeadbeef;
-
-0b111000;
-0b000111;
-0B111000;
-0B000111;
-0o111000;
-0o000111;
-0O111000;
-0O000111;
-0x111000;
-0x000111;
-0X111000;
-0X000111;
-
-1e1;
-1e+1;
-1e-1;
-1.e1;
-.1e1;
-1.1e1;
-1.1e0010;
-.1e+0010;
-.1e-0010;
-
-1E1;
-1E+1;
-1E-1;
-1.E1;
-.1E1;
-1.1E1;
-1.1E0010;
-.1E+0010;
-.1E-0010;
-
-0.5e0;
-0.5e00;
-0.5e+0;
-0.5e+00;
-0.5e-0;
-0.5e-00;
-
-1;
-1.00500;
-1.0;
-1.5;
-1.50;
-0;
-0.00500;
-0.0;
-0.0000;
-.0;
-500600.001230045000;
-1.00500e60;
-1.0e60;
-0.00500e60;
-0.0e60;
-0.0000e60;
-.0e60;
-0.e60;
-0e60;
-500600.001230045000e60;
-10;
-9700;
-10e100;
-```
-
-
-

MODIFY
crates/rome_js_formatter/tests/specs/prettier/js/range/boundary.js.snap
crates/rome_js_formatter/tests/specs/prettier/js/range/boundary.js.snap
---
source: crates/rome_js_formatter/tests/prettier_tests.rs
+info:
+ test_file: js/range/boundary.js
---
# Input
@@ -21,7 +23,7 @@ foo = 1.0000;bar = 1.0000;baz=1.0000;
-foo = 1.0;
-bar = 1.0;
-baz = 1.0;
-+foo = 1.0000;bar = 1.0000;baz=1.0000;
++foo = 1.0000;bar = 1.0;baz=1.0000;
// The range will be 13~26
// `foo` ends at 13, should not format
// `bar` ends at 26, should format
@@ -30,7 +32,7 @@ foo = 1.0000;bar = 1.0000;baz=1.0000;
# Output
```js
-foo = 1.0000;bar = 1.0000;baz=1.0000;
+foo = 1.0000;bar = 1.0;baz=1.0000;
// The range will be 13~26
// `foo` ends at 13, should not format
// `bar` ends at 26, should format

DELETE
crates/rome_js_formatter/tests/specs/prettier/typescript/typeparams/consistent/simple-types.ts.snap
----
-source: crates/rome_js_formatter/tests/prettier_tests.rs
----
-
-# Input
-
-```js
-const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<any> = a;
-const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<null> = a;
-const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<this> = a;
-const foo4: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<void> = a;
-const foo5: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> = a;
-const foo6: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<false> = a;
-const foo7: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<symbol> = a;
-const foo8: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> = a;
-const foo9: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<"STRING"> = a;
-const foo10: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> = a;
-const foo11: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beef> = a;
-const foo12: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beefn> = a;
-```
-
-
-# Prettier differences
-
-```diff
---- Prettier
-+++ Rome
-@@ -18,7 +18,7 @@
- a;
- const foo10: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> =
- a;
--const foo11: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xdeed_beef> =
-+const foo11: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beef> =
- a;
--const foo12: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xdeed_beefn> =
-+const foo12: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beefn> =
- a;
-```
-
-# Output
-
-```js
-const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<any> =
- a;
-const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<null> =
- a;
-const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<this> =
- a;
-const foo4: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<void> =
- a;
-const foo5: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> =
- a;
-const foo6: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<false> =
- a;
-const foo7: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<symbol> =
- a;
-const foo8: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> =
- a;
-const foo9: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<"STRING"> =
- a;
-const foo10: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> =
- a;
-const foo11: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beef> =
- a;
-const foo12: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beefn> =
- a;
-```
-
-
-# Lines exceeding max width of 80 characters
-```
- 1: const foo1: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<any> =
- 3: const foo2: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<null> =
- 5: const foo3: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<this> =
- 7: const foo4: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<void> =
- 9: const foo5: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> =
- 11: const foo6: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<false> =
- 13: const foo7: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<symbol> =
- 15: const foo8: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<true> =
- 17: const foo9: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<"STRING"> =
- 19: const foo10: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0> =
- 21: const foo11: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beef> =
- 23: const foo12: Fooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo<0xDeeD_Beefn> =
-```
-

DELETE
crates/rome_js_formatter/tests/specs/prettier/typescript/webhost/webtsc.ts.snap
----
-source: crates/rome_js_formatter/tests/prettier_tests.rs
----
-
-# Input
-
-```js
-/// <reference path='..\..\src\compiler\tsc.ts'/>
-
-namespace TypeScript.WebTsc {
-
- declare var RealActiveXObject: { new (s: string): any };
-
- function getWScriptSystem() {
- const fso = new RealActiveXObject("Scripting.FileSystemObject");
-
- const fileStream = new ActiveXObject("ADODB.Stream");
- fileStream.Type = 2 /*text*/;
-
- const args: string[] = [];
- for (let i = 0; i < WScript.Arguments.length; i++) {
- args[i] = WScript.Arguments.Item(i);
- }
- return {
- args: args,
- newLine: "\r\n",
- write(s: string): void {
- WScript.StdOut.Write(s);
- },
- writeErr(s: string): void {
- WScript.StdErr.Write(s);
- },
- readFile(fileName: string, encoding?: string): string {
- if (!fso.FileExists(fileName)) {
- return undefined;
- }
- fileStream.Open();
- try {
- if (encoding) {
- fileStream.Charset = encoding;
- fileStream.LoadFromFile(fileName);
- }
- else {
- // Load file and read the first two bytes into a string with no interpretation
- fileStream.Charset = "x-ansi";
- fileStream.LoadFromFile(fileName);
- const bom = fileStream.ReadText(2) || "";
- // Position must be at 0 before encoding can be changed
- fileStream.Position = 0;
- // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
- fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8";
- }
- // ReadText method always strips byte order mark from resulting string
- return fileStream.ReadText();
- }
- catch (e) {
- throw e;
- }
- finally {
- fileStream.Close();
- }
- },
- writeFile(fileName: string, data: string): boolean {
- const f = fso.CreateTextFile(fileName, true);
- f.Write(data);
- f.Close();
- return true;
- },
- resolvePath(path: string): string {
- return fso.GetAbsolutePathName(path);
- },
- fileExists(path: string): boolean {
- return fso.FileExists(path);
- },
- directoryExists(path: string) {
- return fso.FolderExists(path);
- },
- createDirectory(directoryName: string) {
- if (!this.directoryExists(directoryName)) {
- fso.CreateFolder(directoryName);
- }
- },
- getExecutingFilePath() {
- return WScript.ScriptFullName;
- },
- getCurrentDirectory() {
- return "";
- },
- getMemoryUsage() {
- return 0;
- },
- exit(exitCode?: number): void {
- WScript.Quit(exitCode);
- },
- useCaseSensitiveFileNames: false
- };
- }
-
- export function prepareCompiler(currentDir: string, stdOut: ITextWriter, stdErr: ITextWriter) {
- const shell = new RealActiveXObject("WScript.Shell");
- shell.CurrentDirectory = currentDir;
- WScript.ScriptFullName = currentDir + "\\tc.js";
- WScript.StdOut = stdOut;
- WScript.StdErr = stdErr;
- sys = getWScriptSystem();
-
- return (commandLine: string) => {
- ts.executeCommandLine(commandLine.split(" "));
- };
- }
-}
-```
-
-
-# Prettier differences
-
-```diff
---- Prettier
-+++ Rome
-@@ -41,8 +41,8 @@
- // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
- fileStream.Charset =
- bom.length >= 2 &&
-- ((bom.charCodeAt(0) === 0xff && bom.charCodeAt(1) === 0xfe) ||
-- (bom.charCodeAt(0) === 0xfe && bom.charCodeAt(1) === 0xff))
-+ ((bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE) ||
-+ (bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF))
- ? "unicode"
- : "utf-8";
- }
-```
-
-# Output
-
-```js
-/// <reference path='..\..\src\compiler\tsc.ts'/>
-
-namespace TypeScript.WebTsc {
- declare var RealActiveXObject: { new (s: string): any };
-
- function getWScriptSystem() {
- const fso = new RealActiveXObject("Scripting.FileSystemObject");
-
- const fileStream = new ActiveXObject("ADODB.Stream");
- fileStream.Type = 2 /*text*/;
-
- const args: string[] = [];
- for (let i = 0; i < WScript.Arguments.length; i++) {
- args[i] = WScript.Arguments.Item(i);
- }
- return {
- args: args,
- newLine: "\r\n",
- write(s: string): void {
- WScript.StdOut.Write(s);
- },
- writeErr(s: string): void {
- WScript.StdErr.Write(s);
- },
- readFile(fileName: string, encoding?: string): string {
- if (!fso.FileExists(fileName)) {
- return undefined;
- }
- fileStream.Open();
- try {
- if (encoding) {
- fileStream.Charset = encoding;
- fileStream.LoadFromFile(fileName);
- } else {
- // Load file and read the first two bytes into a string with no interpretation
- fileStream.Charset = "x-ansi";
- fileStream.LoadFromFile(fileName);
- const bom = fileStream.ReadText(2) || "";
- // Position must be at 0 before encoding can be changed
- fileStream.Position = 0;
- // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
- fileStream.Charset =
- bom.length >= 2 &&
- ((bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE) ||
- (bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF))
- ? "unicode"
- : "utf-8";
- }
- // ReadText method always strips byte order mark from resulting string
- return fileStream.ReadText();
- } catch (e) {
- throw e;
- } finally {
- fileStream.Close();
- }
- },
- writeFile(fileName: string, data: string): boolean {
- const f = fso.CreateTextFile(fileName, true);
- f.Write(data);
- f.Close();
- return true;
- },
- resolvePath(path: string): string {
- return fso.GetAbsolutePathName(path);
- },
- fileExists(path: string): boolean {
- return fso.FileExists(path);
- },
- directoryExists(path: string) {
- return fso.FolderExists(path);
- },
- createDirectory(directoryName: string) {
- if (!this.directoryExists(directoryName)) {
- fso.CreateFolder(directoryName);
- }
- },
- getExecutingFilePath() {
- return WScript.ScriptFullName;
- },
- getCurrentDirectory() {
- return "";
- },
- getMemoryUsage() {
- return 0;
- },
- exit(exitCode?: number): void {
- WScript.Quit(exitCode);
- },
- useCaseSensitiveFileNames: false,
- };
- }
-
- export function prepareCompiler(
- currentDir: string,
- stdOut: ITextWriter,
- stdErr: ITextWriter,
- ) {
- const shell = new RealActiveXObject("WScript.Shell");
- shell.CurrentDirectory = currentDir;
- WScript.ScriptFullName = currentDir + "\\tc.js";
- WScript.StdOut = stdOut;
- WScript.StdErr = stdErr;
- sys = getWScriptSystem();
-
- return (commandLine: string) => {
- ts.executeCommandLine(commandLine.split(" "));
- };
- }
-}
-```
-
-
-# Lines exceeding max width of 80 characters
-```
- 35: // Load file and read the first two bytes into a string with no interpretation
- 41: // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8
-```
-

feat(rome_js_formatter): number literals, number literal types, bigint literal types (#3554)