Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 94 additions & 62 deletions crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ impl<'a> RawNum<'a> {
Some(RawNum { int, frac, exp })
}

fn normalize(&mut self) -> ScientificNotation<'a> {
fn normalize(&mut self, parse_as_float: bool) -> ScientificNotation<'a> {
if self.int == "0" && !self.frac.is_empty() {
let frac_zeros = self.frac.chars().take_while(|&ch| ch == '0').count();
#[expect(clippy::cast_possible_wrap)]
Expand All @@ -195,11 +195,15 @@ impl<'a> RawNum<'a> {
ScientificNotation { int: self.int, frac: Cow::Borrowed(self.frac), exp }
} else {
let frac = if self.frac.is_empty() {
let int_trimmed = self.int.trim_end_matches('0');
if int_trimmed.len() == 1 {
Cow::Borrowed("")
if parse_as_float {
Cow::Borrowed(&self.int[1..])
} else {
Cow::Borrowed(&int_trimmed[1..])
let int_trimmed = self.int.trim_end_matches('0');
if int_trimmed.len() == 1 {
Cow::Borrowed("")
} else {
Cow::Borrowed(&int_trimmed[1..])
}
}
} else {
Cow::Owned(format!("{}{}", &self.int[1..], self.frac))
Expand Down Expand Up @@ -230,7 +234,7 @@ impl NoLossOfPrecision {

fn base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {
let raw = node.raw.as_ref().unwrap().as_str().cow_replace('_', "");
let Some(raw) = Self::normalize(&raw) else {
let Some(raw) = Self::normalize(&raw, false) else {
return true;
};

Expand All @@ -242,14 +246,18 @@ impl NoLossOfPrecision {

let stored = to_precision(node.value, total_significant_digits);

let Some(stored) = Self::normalize(&stored) else {
let Some(stored) = Self::normalize(&stored, true) else {
return true;
};
raw != stored
}

fn normalize(num: &str) -> Option<ScientificNotation<'_>> {
Some(RawNum::new(num)?.normalize())
fn normalize(num: &str, parse_as_float: bool) -> Option<ScientificNotation<'_>> {
let coefficient = num.trim_start_matches(['+', '-']);
let exp_start =
coefficient.find('e').or_else(|| coefficient.find('E')).unwrap_or(coefficient.len());
let parse_as_float = parse_as_float || coefficient[..exp_start].contains('.');
Some(RawNum::new(num)?.normalize(parse_as_float))
}

pub fn lose_precision(node: &'_ NumericLiteral) -> bool {
Expand Down Expand Up @@ -486,31 +494,42 @@ fn test() {
"var x = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000",
"var x = -0",
"var x = 123.0000000000000000000000",
"var x = 9.00e2",
"var x = 9.000e3",
"var x = 9.0000000000e10",
"var x = 9.00E2",
"var x = 9.000E3",
"var x = 9.100E3",
"var x = 9.0000000000E10",
"var x = 019.5",
"var x = 0195",
"var x = 00195",
"var x = 0008",
"var x = 0e5",
"var x = 12_34_56",
"var x = 12_3.4_56",
"var x = -12_3.4_56",
"var x = -12_34_56",
"var x = 12_3e3_4",
"var x = 123.0e3_4",
"var x = 12_3e-3_4",
"var x = 12_3.0e-3_4",
"var x = -1_23e-3_4",
"var x = -1_23.8e-3_4",
"var x = 1_230000000_00000000_00000_000",
"var x = -1_230000000_00000000_00000_000",
"var x = 0.0_00_000000000_000000000_00123",
"var x = -0.0_00_000000000_000000000_00123",
"var x = 0e5_3",
"var x = 0b11111111111111111111111111111111111111111111111111111",
"var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111",
"var x = 0B11111111111111111111111111111111111111111111111111111",
"var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111",
"var x = 0o377777777777777777",
"var x = 0o3_77_777_777_777_777_777",
"var x = 0O377777777777777777",
"var x = .42",
"var x = 42.",
"var x = 12_34_56", // { "ecmaVersion": 2021 },
"var x = 12_3.4_56", // { "ecmaVersion": 2021 },
"var x = -12_3.4_56", // { "ecmaVersion": 2021 },
"var x = -12_34_56", // { "ecmaVersion": 2021 },
"var x = 12_3e3_4", // { "ecmaVersion": 2021 },
"var x = 123.0e3_4", // { "ecmaVersion": 2021 },
"var x = 12_3e-3_4", // { "ecmaVersion": 2021 },
"var x = 12_3.0e-3_4", // { "ecmaVersion": 2021 },
"var x = -1_23e-3_4", // { "ecmaVersion": 2021 },
"var x = -1_23.8e-3_4", // { "ecmaVersion": 2021 },
"var x = 1_230000000_00000000_00000_000", // { "ecmaVersion": 2021 },
"var x = -1_230000000_00000000_00000_000", // { "ecmaVersion": 2021 },
"var x = 0.0_00_000000000_000000000_00123", // { "ecmaVersion": 2021 },
"var x = -0.0_00_000000000_000000000_00123", // { "ecmaVersion": 2021 },
"var x = 0e5_3", // { "ecmaVersion": 2021 },
"var x = 0b11111111111111111111111111111111111111111111111111111", // { "ecmaVersion": 6 },
"var x = 0b111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111", // { "ecmaVersion": 2021 },
"var x = 0B11111111111111111111111111111111111111111111111111111", // { "ecmaVersion": 6 },
"var x = 0B111_111_111_111_1111_11111_111_11111_1111111111_11111111_111_111", // { "ecmaVersion": 2021 },
"var x = 0o377777777777777777", // { "ecmaVersion": 6 },
"var x = 0o3_77_777_777_777_777_777", // { "ecmaVersion": 2021 },
"var x = 0O377777777777777777", // { "ecmaVersion": 6 },
// "var x = 0377777777777777777", // '0'-prefixed octal literals and octal escape sequences are deprecated
"var x = 0x1FFFFFFFFFFFFF",
"var x = 0X1FFFFFFFFFFFFF",
Expand All @@ -523,8 +542,14 @@ fn test() {
"var x = ['a', 'b']",
"var x = new Date()",
"var x = '9007199254740993'",
"var x = 0x1FFF_FFFF_FFF_FFF",
"var x = 0X1_FFF_FFFF_FFF_FFF",
"var x = 0x1FFF_FFFF_FFF_FFF", // { "ecmaVersion": 2021 },
"var x = 0X1_FFF_FFFF_FFF_FFF", // { "ecmaVersion": 2021 },
"const x = 12345;",
"const x = 123.456;",
"const x = -123.456;",
"const x = 123_456;",
"const x = 123_00_000_000_000_000_000_000_000;",
"const x = 123.000_000_000_000_000_000_000_0;",
"var a = Infinity",
"var a = 480.00",
"var a = -30.00",
Expand All @@ -545,47 +570,54 @@ fn test() {
"var x = -9007199254740993",
"var x = 900719.9254740994",
"var x = -900719.9254740994",
"var x = 900719925474099_3",
"var x = 90_0719925_4740.9_93e3",
"var x = 9.0_0719925_474099_3e15",
"var x = -9_00719_9254_740993",
"var x = 900_719.92_54740_994",
"var x = -900_719.92_5474_0994",
"let x = 9.0_0719925_474099_3e15",
"let x = -9_00719_9254_740993",
"let x = 900_719.92_54740_994",
"let x = -900_719.92_5474_0994",
"const x = 9.0_0719925_474099_3e15",
"const x = -9_00719_9254_740993",
"const x = 900_719.92_54740_994",
"const x = -900_719.92_5474_0994",
"const x = 9.0_0719925_474099_3e15",
"const x = 900_719.92_54740_994",
"let x = -9_00719_9254_740993",
"let x = -900_719.92_5474_0994",
"let x = 9.0_0719925_474099_3e15",
"let x = 900_719.92_54740_994",
"var x = -9_00719_9254_740993", // { "ecmaVersion": 2021 },
"var x = -900_719.92_5474_0994", // { "ecmaVersion": 2021 },
"var x = .9007199254740993e16",
"var x = 9.0_0719925_474099_3e15", // { "ecmaVersion": 2021 },
"var x = 90_0719925_4740.9_93e3", // { "ecmaVersion": 2021 },
"var x = 900_719.92_54740_994", // { "ecmaVersion": 2021 },
"var x = 900719925474099_3", // { "ecmaVersion": 2021 },
"var x = 900719925474099.30e1",
"var x = 90071992547409930e-1",
"var x = 5123000000000000000000000000001",
"var x = -5123000000000000000000000000001",
"var x = 1230000000000000000000000.0",
"var x = 1.0000000000000000000000123",
"var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592",
"var x = 2e999",
"var x = .1230000000000000000000000",
"var x = 0b100000000000000000000000000000000000000000000000000001",
"var x = 0B100000000000000000000000000000000000000000000000000001",
"var x = 0o400000000000000001",
"var x = 0O400000000000000001",
"var x = 0b100000000000000000000000000000000000000000000000000001", // { "ecmaVersion": 6 },
"var x = 0B100000000000000000000000000000000000000000000000000001", // { "ecmaVersion": 6 },
"var x = 0o400000000000000001", // { "ecmaVersion": 6 },
"var x = 0O400000000000000001", // { "ecmaVersion": 6 },
"var x = 0400000000000000001",
"var x = 0x20000000000001",
"var x = 0X20000000000001",
"var x = 5123_00000000000000000000000000_1",
"var x = -5_12300000000000000000000_0000001",
"var x = 123_00000000000000000000_00.0_0",
"var x = 1.0_00000000000000000_0000123",
"var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2",
"var x = 2e9_99",
"var x = .1_23000000000000_00000_0000_0",
"var x = 0b1_0000000000000000000000000000000000000000000000000000_1",
"var x = 0B10000000000_0000000000000000000000000000_000000000000001",
"var x = 0o4_00000000000000_001",
"var x = 0O4_0000000000000000_1",
"var x = 0x2_0000000000001",
"var x = 0X200000_0000000_1",
"var x = 5123_00000000000000000000000000_1", // { "ecmaVersion": 2021 },
"var x = -5_12300000000000000000000_0000001", // { "ecmaVersion": 2021 },
"var x = 123_00000000000000000000_00.0_0", // { "ecmaVersion": 2021 },
"var x = 1.0_00000000000000000_0000123", // { "ecmaVersion": 2021 },
"var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2", // { "ecmaVersion": 2021 },
"var x = 2e9_99", // { "ecmaVersion": 2021 },
"var x = .1_23000000000000_00000_0000_0", // { "ecmaVersion": 2021 },
"var x = 0b1_0000000000000000000000000000000000000000000000000000_1", // { "ecmaVersion": 2021 },
"var x = 0B10000000000_0000000000000000000000000000_000000000000001", // { "ecmaVersion": 2021 },
"var x = 0o4_00000000000000_001", // { "ecmaVersion": 2021 },
"var x = 0O4_0000000000000000_1", // { "ecmaVersion": 2021 },
"var x = 0x2_0000000000001", // { "ecmaVersion": 2021 },
"var x = 0X200000_0000000_1", // { "ecmaVersion": 2021 },
"const x = 9007199254740993;",
"const x = 9_007_199_254_740_993;",
"const x = 9_007_199_254_740.993e3;",
"const x = 0b100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001;",
"var x = 1e18_446_744_073_709_551_615",
"var x = 96215808661.52751e-84",
];
Expand Down
Loading
Loading