diff --git a/CHANGELOG.md b/CHANGELOG.md index f46ef7ecec6e..a64418037974 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,10 +59,6 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom ### Linter -#### Enhancements - -- [noUselessTernary](https://biomejs.dev/linter/rules/no-useless-ternary/) now provides unsafe code fixes. Contributed by @vasucp1207 - #### New features - Add the rule [noSkippedTests](https://biomejs.dev/linter/rules/no-skipped-tests), to disallow skipped tests: @@ -89,6 +85,32 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom ``` Contributed by @DaniGuardiola +#### Enhancements + +- [noUselessTernary](https://biomejs.dev/linter/rules/no-useless-ternary) now provides unsafe code fixes. Contributed by @vasucp1207 + +- [noApproximativeNumericConstant](https://biomejs.dev/linter/rules/no-approximative-numeric-constant) now provides unsafe code fixes and handle numbers without leading zero and numbers with digit separators. + + The following numbers are now reported as approximated constants. + + ```js + 3.14_15; // PI + .4342; // LOG10E + ``` + + Contributed by @Conaclos + +- [noPrecisionLoss](https://biomejs.dev/linter/rules/no-precision-loss) no longer reports number with extra zeros. + + The following numbers are now valid. + + ```js + .1230000000000000000000000; + 1230000000000000000000000.0; + ``` + + Contributed by @Conaclos + #### Bug fixes - Fix [#1651](https://github.com/biomejs/biome/issues/1651). [noVar](https://biomejs.dev/linter/rules/no-var/) now ignores TsGlobalDeclaration. Contributed by @vasucp1207 diff --git a/crates/biome_js_analyze/src/analyzers/correctness/no_precision_loss.rs b/crates/biome_js_analyze/src/analyzers/correctness/no_precision_loss.rs index 1ba3c866f255..aa20b32ddbde 100644 --- a/crates/biome_js_analyze/src/analyzers/correctness/no_precision_loss.rs +++ b/crates/biome_js_analyze/src/analyzers/correctness/no_precision_loss.rs @@ -22,23 +22,15 @@ declare_rule! { /// ``` /// /// ```js,expect_diagnostic - /// const x = 5123000000000000000000000000001 + /// const x = 5.123000000000000000000000000001 /// ``` /// /// ```js,expect_diagnostic - /// const x = 1230000000000000000000000.0 + /// const x = 0x20000000000001 /// ``` /// /// ```js,expect_diagnostic - /// const x = .1230000000000000000000000 - /// ``` - /// - /// ```js,expect_diagnostic - /// const x = 0X20000000000001 - /// ``` - /// - /// ```js,expect_diagnostic - /// const x = 0X2_000000000_0001; + /// const x = 0x2_000000000_0001; /// ``` /// /// ### Valid @@ -105,12 +97,13 @@ fn is_precision_lost(node: &JsNumberLiteralExpression) -> Option { } fn is_precision_lost_in_base_10(num: &str) -> Option { + const MAX_SIGNIFICANT_DIGITS_BASE10: u32 = 17; let normalized = NormalizedNumber::new(num); let precision = normalized.precision(); if precision == 0 { return Some(false); } - if precision > 100 { + if precision > MAX_SIGNIFICANT_DIGITS_BASE10 as usize { return Some(true); } let parsed = num.parse::().ok()?; @@ -118,8 +111,8 @@ fn is_precision_lost_in_base_10(num: &str) -> Option { Some(stored_num != normalized.to_scientific()) } -fn is_precision_lost_in_base_other(num: &str, radix: u32) -> bool { - let parsed = match i64::from_str_radix(num, radix) { +fn is_precision_lost_in_base_other(num: &str, radix: u8) -> bool { + let parsed = match i64::from_str_radix(num, radix as u32) { Ok(x) => x, Err(e) => { return matches!( @@ -145,7 +138,7 @@ fn remove_trailing_zeros(num: &str) -> &str { } #[derive(Debug)] -/// Normalized number in the form `0.{digits}.{digits_rest}e{exponent}` +/// Normalized number in the form `0.{digits}{digits_rest}e{exponent}` struct NormalizedNumber<'a> { digits: &'a str, digits_rest: &'a str, @@ -155,49 +148,44 @@ struct NormalizedNumber<'a> { impl NormalizedNumber<'_> { fn new(num: &str) -> NormalizedNumber<'_> { let num = remove_leading_zeros(num); - let mut split = num.splitn(2, ['e', 'E']); - - // SAFETY: unwrap is ok because even an empty string will produce one part. - let mantissa = split.next().unwrap(); - let exponent = split.next(); - let mut mantissa_parts = mantissa.splitn(2, '.'); - - // SAFETY: unwrap is ok because even an empty string will produce one part. - let mut normalized = match (mantissa_parts.next().unwrap(), mantissa_parts.next()) { - ("", Some(fraction)) => { + let (mantissa, exponent) = num + .split_once(['e', 'E']) + .and_then(|(mantissa, exponent)| Some((mantissa, exponent.parse::().ok()?))) + .unwrap_or((num, 0)); + match mantissa.split_once(['.']) { + None => NormalizedNumber { + digits: remove_trailing_zeros(mantissa), + digits_rest: "", + exponent: exponent + mantissa.len() as isize, + }, + Some(("", fraction)) => { let digits = remove_leading_zeros(fraction); NormalizedNumber { - digits, + digits: remove_trailing_zeros(digits), digits_rest: "", - exponent: digits.len() as isize - fraction.len() as isize, + exponent: digits.len() as isize - fraction.len() as isize + exponent, } } - (integer, Some(fraction)) => NormalizedNumber { - digits: integer, - digits_rest: fraction, - exponent: integer.len() as isize, - }, - (integer, None) => { - let digits = remove_trailing_zeros(integer); + Some((integer, fraction)) => { + let fraction = remove_trailing_zeros(fraction); + let digits = if fraction.is_empty() { + remove_trailing_zeros(integer) + } else { + integer + }; NormalizedNumber { digits, - digits_rest: "", - exponent: integer.len() as isize, + digits_rest: fraction, + exponent: exponent + integer.len() as isize, } } - }; - - if let Some(exponent) = exponent.and_then(|it| it.parse::().ok()) { - normalized.exponent += exponent; } - - normalized } fn to_scientific(&self) -> String { let fraction = &self.digits[1..]; if fraction.is_empty() && self.digits_rest.is_empty() { - format!("{}e{}", &self.digits[..1], self.exponent - 1) + format!("{}e{}", self.digits, self.exponent - 1) } else { format!( "{}.{}{}e{}", diff --git a/crates/biome_js_analyze/src/analyzers/suspicious/no_approximative_numeric_constant.rs b/crates/biome_js_analyze/src/analyzers/suspicious/no_approximative_numeric_constant.rs index 4526428ac7c1..9ebfd93a0003 100644 --- a/crates/biome_js_analyze/src/analyzers/suspicious/no_approximative_numeric_constant.rs +++ b/crates/biome_js_analyze/src/analyzers/suspicious/no_approximative_numeric_constant.rs @@ -1,12 +1,25 @@ -use std::f64::consts as f64; +use std::cmp::Ordering; -use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic, RuleSource}; +use biome_analyze::{ + context::RuleContext, declare_rule, ActionCategory, Ast, FixKind, Rule, RuleDiagnostic, + RuleSource, +}; use biome_console::markup; -use biome_js_syntax::JsNumberLiteralExpression; -use biome_rowan::AstNode; +use biome_diagnostics::Applicability; +use biome_js_factory::make; +use biome_js_syntax::{ + numbers::split_into_radix_and_number, AnyJsExpression, AnyJsLiteralExpression, + JsNumberLiteralExpression, T, +}; +use biome_rowan::{AstNode, BatchMutationExt}; + +use crate::JsRuleAction; declare_rule! { - /// Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type. + /// Use standard constants instead of approximated literals. + /// + /// Usually, the definition in the standard library is more precise than + /// what people come up with or the used constant exceeds the maximum precision of the number type. /// /// ## Examples /// @@ -15,6 +28,7 @@ declare_rule! { /// ```js,expect_diagnostic /// let x = 3.141; /// ``` + /// /// ```js,expect_diagnostic /// let x = 2.302; /// ``` @@ -23,7 +37,9 @@ declare_rule! { /// /// ```js /// let x = Math.PI; + /// let y = 3.14; /// ``` + /// /// ```js /// let x = Math.LN10; /// ``` @@ -32,81 +48,113 @@ declare_rule! { name: "noApproximativeNumericConstant", source: RuleSource::Clippy("approx_constant"), recommended: false, + fix_kind: FixKind::Unsafe, } } impl Rule for NoApproximativeNumericConstant { type Query = Ast; - type State = (); + type State = &'static str; type Signals = Option; type Options = (); fn run(ctx: &RuleContext) -> Self::Signals { - let node = ctx.query(); - - if get_approximative_literal_diagnostic(node).is_some() { - Some(()) - } else { - None + let token = ctx.query().value_token().ok()?; + let num = token.text_trimmed(); + let (10, num) = split_into_radix_and_number(num) else { + return None; + }; + let (decimal, fraction) = num.split_once('.')?; + if fraction.len() < (MIN_FRACTION_DIGITS as usize) + || !matches!(decimal, "" | "0" | "1" | "2" | "3") + || fraction.contains(['e', 'E']) + { + return None; + } + let num = num.trim_matches('0'); + for (constant, name) in KNOWN_CONSTS { + let is_constant_approximated = match constant.len().cmp(&num.len()) { + Ordering::Less => is_approx_const(num, constant), + Ordering::Equal => constant == num, + Ordering::Greater => is_approx_const(constant, num), + }; + if is_constant_approximated { + return Some(name); + } } + None } fn diagnostic(ctx: &RuleContext, _: &Self::State) -> Option { let node = ctx.query(); - get_approximative_literal_diagnostic(node) + Some(RuleDiagnostic::new( + rule_category!(), + node.range(), + markup! { "Prefer constants from the standard library." }, + )) } -} - -// Tuples are of the form (constant, name, min_digits) -const KNOWN_CONSTS: [(f64, &str, usize); 8] = [ - (f64::E, "E", 4), - (f64::LN_10, "LN10", 4), - (f64::LN_2, "LN2", 4), - (f64::LOG10_E, "LOG10E", 4), - (f64::LOG2_E, "LOG2E", 4), - (f64::PI, "PI", 4), - (f64::FRAC_1_SQRT_2, "SQRT1_2", 4), - (f64::SQRT_2, "SQRT2", 4), -]; -fn get_approximative_literal_diagnostic( - node: &JsNumberLiteralExpression, -) -> Option { - let binding = node.text(); - let s = binding.trim(); - if s.parse::().is_err() { - return None; + fn action(ctx: &RuleContext, constant_name: &Self::State) -> Option { + let node = ctx.query(); + let new_node = make::js_static_member_expression( + make::js_identifier_expression(make::js_reference_identifier(make::ident("Math"))) + .into(), + make::token(T![.]), + make::js_name(make::ident(constant_name)).into(), + ); + let mut mutation = ctx.root().begin(); + mutation.replace_node( + AnyJsExpression::AnyJsLiteralExpression(AnyJsLiteralExpression::from(node.clone())), + AnyJsExpression::from(new_node), + ); + Some(JsRuleAction { + category: ActionCategory::QuickFix, + applicability: Applicability::MaybeIncorrect, + message: markup! { "Use ""Math."{ constant_name }" instead." } + .to_owned(), + mutation, + }) } +} - for &(constant, name, min_digits) in &KNOWN_CONSTS { - if is_approx_const(constant, s, min_digits) { - return Some( - RuleDiagnostic::new( - rule_category!(), - node.syntax().text_trimmed_range(), - markup! { "Prefer constants from the standard library." }, - ) - .note(markup! { "Use ""Math."{ name }" instead." }), - ); - } - } +const MIN_FRACTION_DIGITS: u8 = 3; - None -} +// Tuples are of the form (constant, name) +const KNOWN_CONSTS: [(&str, &str); 8] = [ + ("2.718281828459045", "E"), + ("2.302585092994046", "LN10"), + (".6931471805599453", "LN2"), + (".4342944819032518", "LOG10E"), + ("1.4426950408889634", "LOG2E"), + ("3.141592653589793", "PI"), + (".7071067811865476", "SQRT1_2"), + ("1.4142135623730951", "SQRT2"), +]; -/// Returns `false` if the number of significant figures in `value` are -/// less than `min_digits`; otherwise, returns true if `value` is equal -/// to `constant`, rounded to the number of digits present in `value`. -/// Taken from rust-clippy/clippy_lints: -/// https://github.com/rust-lang/rust-clippy/blob/9554e477c29e6ddca9e5cdce71524341ef9d48e8/clippy_lints/src/approx_const.rs#L118-L132 -fn is_approx_const(constant: f64, value: &str, min_digits: usize) -> bool { - if value.len() <= min_digits { - false - } else if constant.to_string().starts_with(value) { +/// Returns true if `value` is equal to `constant`, +/// or rounded to the number of digits present in `value`. +fn is_approx_const(constant: &str, value: &str) -> bool { + if constant.starts_with(value) { // The value is a truncated constant - true - } else { - let round_const = format!("{constant:.*}", value.len() - 2); - value == round_const + return true; + } + let (digits, last_digit) = value.split_at(value.len() - 1); + if constant.starts_with(digits) { + let Ok(last_digit) = last_digit.parse::() else { + return false; + }; + let Ok(extra_constant_digit) = constant[value.len()..value.len() + 1].parse::() else { + return false; + }; + let can_be_rounded = extra_constant_digit < 5; + if can_be_rounded { + return false; + } + let Ok(constant_digit) = constant[digits.len()..digits.len() + 1].parse::() else { + return false; + }; + let rounded_constant_digit = constant_digit + 1; + return last_digit == rounded_constant_digit; } + false } diff --git a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js index d57ba512b604..38964c00c783 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js @@ -13,11 +13,9 @@ var x = 900_719.92_54740_994 var x = -900_719.92_5474_0994 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 @@ -27,15 +25,12 @@ 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 - \ No newline at end of file +var x = 0X200000_0000000_1 \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js.snap index d4ac16b6b638..0685d2efa13d 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/invalid.js.snap @@ -19,11 +19,9 @@ var x = 900_719.92_54740_994 var x = -900_719.92_5474_0994 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 @@ -33,18 +31,15 @@ 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 - ``` # Diagnostics @@ -261,7 +256,7 @@ invalid.js:14:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ > 14 │ var x = 5123000000000000000000000000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 15 │ var x = -5123000000000000000000000000001 - 16 │ var x = 1230000000000000000000000.0 + 16 │ var x = 1.0000000000000000000000123 i The value at runtime will be 5123000000000000000000000000000 @@ -277,8 +272,8 @@ invalid.js:15:10 lint/correctness/noPrecisionLoss ━━━━━━━━━━ 14 │ var x = 5123000000000000000000000000001 > 15 │ var x = -5123000000000000000000000000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 16 │ var x = 1230000000000000000000000.0 - 17 │ var x = 1.0000000000000000000000123 + 16 │ var x = 1.0000000000000000000000123 + 17 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 i The value at runtime will be 5123000000000000000000000000000 @@ -292,12 +287,12 @@ invalid.js:16:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ 14 │ var x = 5123000000000000000000000000001 15 │ var x = -5123000000000000000000000000001 - > 16 │ var x = 1230000000000000000000000.0 + > 16 │ var x = 1.0000000000000000000000123 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 17 │ var x = 1.0000000000000000000000123 - 18 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 + 17 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 + 18 │ var x = 2e999 - i The value at runtime will be 1230000000000000000000000 + i The value at runtime will be 1 ``` @@ -308,28 +303,11 @@ invalid.js:17:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ! This number literal will lose precision at runtime. 15 │ var x = -5123000000000000000000000000001 - 16 │ var x = 1230000000000000000000000.0 - > 17 │ var x = 1.0000000000000000000000123 - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 18 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 - 19 │ var x = 2e999 - - i The value at runtime will be 1 - - -``` - -``` -invalid.js:18:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This number literal will lose precision at runtime. - - 16 │ var x = 1230000000000000000000000.0 - 17 │ var x = 1.0000000000000000000000123 - > 18 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 + 16 │ var x = 1.0000000000000000000000123 + > 17 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 19 │ var x = 2e999 - 20 │ var x = .1230000000000000000000000 + 18 │ var x = 2e999 + 19 │ var x = 0b100000000000000000000000000000000000000000000000000001 i The value at runtime will be 17498005798264095000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -337,16 +315,16 @@ invalid.js:18:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:19:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:18:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 17 │ var x = 1.0000000000000000000000123 - 18 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 - > 19 │ var x = 2e999 + 16 │ var x = 1.0000000000000000000000123 + 17 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 + > 18 │ var x = 2e999 │ ^^^^^ - 20 │ var x = .1230000000000000000000000 - 21 │ var x = 0b100000000000000000000000000000000000000000000000000001 + 19 │ var x = 0b100000000000000000000000000000000000000000000000000001 + 20 │ var x = 0B100000000000000000000000000000000000000000000000000001 i The value at runtime will be inf @@ -354,33 +332,16 @@ invalid.js:19:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:20:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This number literal will lose precision at runtime. - - 18 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 - 19 │ var x = 2e999 - > 20 │ var x = .1230000000000000000000000 - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^ - 21 │ var x = 0b100000000000000000000000000000000000000000000000000001 - 22 │ var x = 0B100000000000000000000000000000000000000000000000000001 - - i The value at runtime will be 0.123 - - -``` - -``` -invalid.js:21:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:19:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 19 │ var x = 2e999 - 20 │ var x = .1230000000000000000000000 - > 21 │ var x = 0b100000000000000000000000000000000000000000000000000001 + 17 │ var x = 17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592 + 18 │ var x = 2e999 + > 19 │ var x = 0b100000000000000000000000000000000000000000000000000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 22 │ var x = 0B100000000000000000000000000000000000000000000000000001 - 23 │ var x = 0o400000000000000001 + 20 │ var x = 0B100000000000000000000000000000000000000000000000000001 + 21 │ var x = 0o400000000000000001 i The value at runtime will be 9007199254740992 @@ -388,16 +349,16 @@ invalid.js:21:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:22:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:20:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 20 │ var x = .1230000000000000000000000 - 21 │ var x = 0b100000000000000000000000000000000000000000000000000001 - > 22 │ var x = 0B100000000000000000000000000000000000000000000000000001 + 18 │ var x = 2e999 + 19 │ var x = 0b100000000000000000000000000000000000000000000000000001 + > 20 │ var x = 0B100000000000000000000000000000000000000000000000000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 23 │ var x = 0o400000000000000001 - 24 │ var x = 0O400000000000000001 + 21 │ var x = 0o400000000000000001 + 22 │ var x = 0O400000000000000001 i The value at runtime will be 9007199254740992 @@ -405,16 +366,16 @@ invalid.js:22:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:23:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:21:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 21 │ var x = 0b100000000000000000000000000000000000000000000000000001 - 22 │ var x = 0B100000000000000000000000000000000000000000000000000001 - > 23 │ var x = 0o400000000000000001 + 19 │ var x = 0b100000000000000000000000000000000000000000000000000001 + 20 │ var x = 0B100000000000000000000000000000000000000000000000000001 + > 21 │ var x = 0o400000000000000001 │ ^^^^^^^^^^^^^^^^^^^^ - 24 │ var x = 0O400000000000000001 - 25 │ var x = 0400000000000000001 + 22 │ var x = 0O400000000000000001 + 23 │ var x = 0400000000000000001 i The value at runtime will be 9007199254740992 @@ -422,16 +383,16 @@ invalid.js:23:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:24:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:22:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 22 │ var x = 0B100000000000000000000000000000000000000000000000000001 - 23 │ var x = 0o400000000000000001 - > 24 │ var x = 0O400000000000000001 + 20 │ var x = 0B100000000000000000000000000000000000000000000000000001 + 21 │ var x = 0o400000000000000001 + > 22 │ var x = 0O400000000000000001 │ ^^^^^^^^^^^^^^^^^^^^ - 25 │ var x = 0400000000000000001 - 26 │ var x = 0x20000000000001 + 23 │ var x = 0400000000000000001 + 24 │ var x = 0x20000000000001 i The value at runtime will be 9007199254740992 @@ -439,16 +400,16 @@ invalid.js:24:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:25:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:23:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 23 │ var x = 0o400000000000000001 - 24 │ var x = 0O400000000000000001 - > 25 │ var x = 0400000000000000001 + 21 │ var x = 0o400000000000000001 + 22 │ var x = 0O400000000000000001 + > 23 │ var x = 0400000000000000001 │ ^^^^^^^^^^^^^^^^^^^ - 26 │ var x = 0x20000000000001 - 27 │ var x = 0X20000000000001 + 24 │ var x = 0x20000000000001 + 25 │ var x = 0X20000000000001 i The value at runtime will be 9007199254740992 @@ -456,16 +417,16 @@ invalid.js:25:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:26:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:24:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 24 │ var x = 0O400000000000000001 - 25 │ var x = 0400000000000000001 - > 26 │ var x = 0x20000000000001 + 22 │ var x = 0O400000000000000001 + 23 │ var x = 0400000000000000001 + > 24 │ var x = 0x20000000000001 │ ^^^^^^^^^^^^^^^^ - 27 │ var x = 0X20000000000001 - 28 │ var x = 5123_00000000000000000000000000_1 + 25 │ var x = 0X20000000000001 + 26 │ var x = 5123_00000000000000000000000000_1 i The value at runtime will be 9007199254740992 @@ -473,16 +434,16 @@ invalid.js:26:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:27:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:25:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 25 │ var x = 0400000000000000001 - 26 │ var x = 0x20000000000001 - > 27 │ var x = 0X20000000000001 + 23 │ var x = 0400000000000000001 + 24 │ var x = 0x20000000000001 + > 25 │ var x = 0X20000000000001 │ ^^^^^^^^^^^^^^^^ - 28 │ var x = 5123_00000000000000000000000000_1 - 29 │ var x = -5_12300000000000000000000_0000001 + 26 │ var x = 5123_00000000000000000000000000_1 + 27 │ var x = -5_12300000000000000000000_0000001 i The value at runtime will be 9007199254740992 @@ -490,16 +451,16 @@ invalid.js:27:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:28:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:26:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 26 │ var x = 0x20000000000001 - 27 │ var x = 0X20000000000001 - > 28 │ var x = 5123_00000000000000000000000000_1 + 24 │ var x = 0x20000000000001 + 25 │ var x = 0X20000000000001 + > 26 │ var x = 5123_00000000000000000000000000_1 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 29 │ var x = -5_12300000000000000000000_0000001 - 30 │ var x = 123_00000000000000000000_00.0_0 + 27 │ var x = -5_12300000000000000000000_0000001 + 28 │ var x = 1.0_00000000000000000_0000123 i The value at runtime will be 5123000000000000000000000000000 @@ -507,16 +468,16 @@ invalid.js:28:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:29:10 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:27:10 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 27 │ var x = 0X20000000000001 - 28 │ var x = 5123_00000000000000000000000000_1 - > 29 │ var x = -5_12300000000000000000000_0000001 + 25 │ var x = 0X20000000000001 + 26 │ var x = 5123_00000000000000000000000000_1 + > 27 │ var x = -5_12300000000000000000000_0000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 30 │ var x = 123_00000000000000000000_00.0_0 - 31 │ var x = 1.0_00000000000000000_0000123 + 28 │ var x = 1.0_00000000000000000_0000123 + 29 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 i The value at runtime will be 5123000000000000000000000000000 @@ -524,33 +485,16 @@ invalid.js:29:10 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:30:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This number literal will lose precision at runtime. - - 28 │ var x = 5123_00000000000000000000000000_1 - 29 │ var x = -5_12300000000000000000000_0000001 - > 30 │ var x = 123_00000000000000000000_00.0_0 - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 31 │ var x = 1.0_00000000000000000_0000123 - 32 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 - - i The value at runtime will be 1230000000000000000000000 - - -``` - -``` -invalid.js:31:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:28:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 29 │ var x = -5_12300000000000000000000_0000001 - 30 │ var x = 123_00000000000000000000_00.0_0 - > 31 │ var x = 1.0_00000000000000000_0000123 + 26 │ var x = 5123_00000000000000000000000000_1 + 27 │ var x = -5_12300000000000000000000_0000001 + > 28 │ var x = 1.0_00000000000000000_0000123 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 32 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 - 33 │ var x = 2e9_99 + 29 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 + 30 │ var x = 2e9_99 i The value at runtime will be 1 @@ -558,16 +502,16 @@ invalid.js:31:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:32:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:29:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 30 │ var x = 123_00000000000000000000_00.0_0 - 31 │ var x = 1.0_00000000000000000_0000123 - > 32 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 + 27 │ var x = -5_12300000000000000000000_0000001 + 28 │ var x = 1.0_00000000000000000_0000123 + > 29 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 33 │ var x = 2e9_99 - 34 │ var x = .1_23000000000000_00000_0000_0 + 30 │ var x = 2e9_99 + 31 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 i The value at runtime will be 17498005798264095000000000000000000000000000000000000000000000000000000000000000000000000000000000000 @@ -575,16 +519,16 @@ invalid.js:32:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:33:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:30:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 31 │ var x = 1.0_00000000000000000_0000123 - 32 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 - > 33 │ var x = 2e9_99 + 28 │ var x = 1.0_00000000000000000_0000123 + 29 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 + > 30 │ var x = 2e9_99 │ ^^^^^^ - 34 │ var x = .1_23000000000000_00000_0000_0 - 35 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 + 31 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 + 32 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 i The value at runtime will be inf @@ -592,33 +536,16 @@ invalid.js:33:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:34:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ - - ! This number literal will lose precision at runtime. - - 32 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 - 33 │ var x = 2e9_99 - > 34 │ var x = .1_23000000000000_00000_0000_0 - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 35 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 - 36 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 - - i The value at runtime will be 0.123 - - -``` - -``` -invalid.js:35:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:31:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 33 │ var x = 2e9_99 - 34 │ var x = .1_23000000000000_00000_0000_0 - > 35 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 + 29 │ var x = 174_980057982_640953949800178169_409709228253554471456994_914061648512796239935950073857881054_1618443059_2 + 30 │ var x = 2e9_99 + > 31 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 36 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 - 37 │ var x = 0o4_00000000000000_001 + 32 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 + 33 │ var x = 0o4_00000000000000_001 i The value at runtime will be 9007199254740992 @@ -626,16 +553,16 @@ invalid.js:35:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:36:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:32:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 34 │ var x = .1_23000000000000_00000_0000_0 - 35 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 - > 36 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 + 30 │ var x = 2e9_99 + 31 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 + > 32 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - 37 │ var x = 0o4_00000000000000_001 - 38 │ var x = 0O4_0000000000000000_1 + 33 │ var x = 0o4_00000000000000_001 + 34 │ var x = 0O4_0000000000000000_1 i The value at runtime will be 9007199254740992 @@ -643,16 +570,16 @@ invalid.js:36:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:37:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:33:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 35 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 - 36 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 - > 37 │ var x = 0o4_00000000000000_001 + 31 │ var x = 0b1_0000000000000000000000000000000000000000000000000000_1 + 32 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 + > 33 │ var x = 0o4_00000000000000_001 │ ^^^^^^^^^^^^^^^^^^^^^^ - 38 │ var x = 0O4_0000000000000000_1 - 39 │ var x = 0x2_0000000000001 + 34 │ var x = 0O4_0000000000000000_1 + 35 │ var x = 0x2_0000000000001 i The value at runtime will be 9007199254740992 @@ -660,16 +587,16 @@ invalid.js:37:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:38:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:34:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 36 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 - 37 │ var x = 0o4_00000000000000_001 - > 38 │ var x = 0O4_0000000000000000_1 + 32 │ var x = 0B10000000000_0000000000000000000000000000_000000000000001 + 33 │ var x = 0o4_00000000000000_001 + > 34 │ var x = 0O4_0000000000000000_1 │ ^^^^^^^^^^^^^^^^^^^^^^ - 39 │ var x = 0x2_0000000000001 - 40 │ var x = 0X200000_0000000_1 + 35 │ var x = 0x2_0000000000001 + 36 │ var x = 0X200000_0000000_1 i The value at runtime will be 9007199254740992 @@ -677,16 +604,15 @@ invalid.js:38:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:39:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:35:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 37 │ var x = 0o4_00000000000000_001 - 38 │ var x = 0O4_0000000000000000_1 - > 39 │ var x = 0x2_0000000000001 + 33 │ var x = 0o4_00000000000000_001 + 34 │ var x = 0O4_0000000000000000_1 + > 35 │ var x = 0x2_0000000000001 │ ^^^^^^^^^^^^^^^^^ - 40 │ var x = 0X200000_0000000_1 - 41 │ + 36 │ var x = 0X200000_0000000_1 i The value at runtime will be 9007199254740992 @@ -694,15 +620,14 @@ invalid.js:39:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━ ``` ``` -invalid.js:40:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:36:9 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! This number literal will lose precision at runtime. - 38 │ var x = 0O4_0000000000000000_1 - 39 │ var x = 0x2_0000000000001 - > 40 │ var x = 0X200000_0000000_1 + 34 │ var x = 0O4_0000000000000000_1 + 35 │ var x = 0x2_0000000000001 + > 36 │ var x = 0X200000_0000000_1 │ ^^^^^^^^^^^^^^^^^^ - 41 │ i The value at runtime will be 9007199254740992 diff --git a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js index f9a1a51fc82f..f28161205c3e 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js +++ b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js @@ -67,3 +67,12 @@ var x = '9007199254740993' var x = 0x1FFF_FFFF_FFF_FFF var x = 0X1_FFF_FFFF_FFF_FFF + +// Ignore extra zeros +.1_23000000000000_00000_0000_0; +.1230000000000000000000000; +1230000000000000000000000.0; +123_00000000000000000000_00.0_0; + +var MAX = 1.7976931348623157e+308; +var MIN = 5e-324; \ No newline at end of file diff --git a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js.snap b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js.snap index d116f42f37ce..862b8cc5feea 100644 --- a/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js.snap +++ b/crates/biome_js_analyze/tests/specs/correctness/noPrecisionLoss/valid.js.snap @@ -74,6 +74,14 @@ var x = '9007199254740993' var x = 0x1FFF_FFFF_FFF_FFF var x = 0X1_FFF_FFFF_FFF_FFF +// Ignore extra zeros +.1_23000000000000_00000_0000_0; +.1230000000000000000000000; +1230000000000000000000000.0; +123_00000000000000000000_00.0_0; + +var MAX = 1.7976931348623157e+308; +var MIN = 5e-324; ``` diff --git a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js index 58ec952dd24a..de251420ec3a 100644 --- a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js +++ b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js @@ -4,6 +4,7 @@ const z = 2.3025; const constants = [ 2.718281, // E + 2.718_281, // E with separator 2.302585, // LN10 0.693147, // LN2 0.434294, // LOG10E @@ -23,3 +24,38 @@ const constants1 = [ 0.707, // SQRT1_2 1.414, // SQRT2 ]; + +const exact = [ + 2.718281828459045, // E + 2.302585092994046, // LN10 + 0.6931471805599453, // LN2 + 0.4342944819032518, // LOG10E + 1.4426950408889634, // LOG2E + 3.141592653589793, // PI + 0.7071067811865476, // SQRT1_2 + .7071067811865476, // SQRT1_2 without leading 0 + 1.4142135623730951, // SQRT2 +]; + +const rounded = [ + // rounded + 2.7183, // E + 2.302585093, // LN10 + 0.6931471806, // LN2 + 0.4342944819033, // LOG10E + 1.442695040889, // LOG2E + 3.1415926535898, // PI + 0.70710678118655, // SQRT1_2 + 1.4142135623731, // SQRT2 +]; + +const precisionLoss = [ + 2.71828182845904523536028747135266250, // E + 2.30258509299404568401799145468436421, // LN10 + 0.693147180559945309417232121458176568, // LN2 + 0.301029995663981195213738894724493027, // LOG10E + 1.44269504088896340735992468100189214, // LOG2E + 3.14159265358979323846264338327950288, // PI + 0.707106781186547524400844362104849039, // SQRT1_2 + 1.41421356237309504880168872420969808, // SQRT2 +]; diff --git a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js.snap b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js.snap index c6787f4a40c0..2f3a532f4981 100644 --- a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js.snap +++ b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/invalid.js.snap @@ -10,6 +10,7 @@ const z = 2.3025; const constants = [ 2.718281, // E + 2.718_281, // E with separator 2.302585, // LN10 0.693147, // LN2 0.434294, // LOG10E @@ -30,11 +31,46 @@ const constants1 = [ 1.414, // SQRT2 ]; +const exact = [ + 2.718281828459045, // E + 2.302585092994046, // LN10 + 0.6931471805599453, // LN2 + 0.4342944819032518, // LOG10E + 1.4426950408889634, // LOG2E + 3.141592653589793, // PI + 0.7071067811865476, // SQRT1_2 + .7071067811865476, // SQRT1_2 without leading 0 + 1.4142135623730951, // SQRT2 +]; + +const rounded = [ + // rounded + 2.7183, // E + 2.302585093, // LN10 + 0.6931471806, // LN2 + 0.4342944819033, // LOG10E + 1.442695040889, // LOG2E + 3.1415926535898, // PI + 0.70710678118655, // SQRT1_2 + 1.4142135623731, // SQRT2 +]; + +const precisionLoss = [ + 2.71828182845904523536028747135266250, // E + 2.30258509299404568401799145468436421, // LN10 + 0.693147180559945309417232121458176568, // LN2 + 0.301029995663981195213738894724493027, // LOG10E + 1.44269504088896340735992468100189214, // LOG2E + 3.14159265358979323846264338327950288, // PI + 0.707106781186547524400844362104849039, // SQRT1_2 + 1.41421356237309504880168872420969808, // SQRT2 +]; + ``` # Diagnostics ``` -invalid.js:1:11 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:1:11 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. @@ -43,13 +79,18 @@ invalid.js:1:11 lint/suspicious/noApproximativeNumericConstant ━━━━━ 2 │ const y = 2.302; 3 │ const z = 2.3025; - i Use Math.PI instead. + i Unsafe fix: Use Math.PI instead. + + 1 │ - const·x·=·3.141; + 1 │ + const·x·=·Math.PI; + 2 2 │ const y = 2.302; + 3 3 │ const z = 2.3025; ``` ``` -invalid.js:2:11 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:2:11 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. @@ -59,13 +100,19 @@ invalid.js:2:11 lint/suspicious/noApproximativeNumericConstant ━━━━━ 3 │ const z = 2.3025; 4 │ - i Use Math.LN10 instead. + i Unsafe fix: Use Math.LN10 instead. + + 1 1 │ const x = 3.141; + 2 │ - const·y·=·2.302; + 2 │ + const·y·=·Math.LN10; + 3 3 │ const z = 2.3025; + 4 4 │ ``` ``` -invalid.js:3:11 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:3:11 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. @@ -76,277 +123,946 @@ invalid.js:3:11 lint/suspicious/noApproximativeNumericConstant ━━━━━ 4 │ 5 │ const constants = [ - i Use Math.LN10 instead. + i Unsafe fix: Use Math.LN10 instead. + + 1 1 │ const x = 3.141; + 2 2 │ const y = 2.302; + 3 │ - const·z·=·2.3025; + 3 │ + const·z·=·Math.LN10; + 4 4 │ + 5 5 │ const constants = [ ``` ``` -invalid.js:6:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:6:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. 5 │ const constants = [ > 6 │ 2.718281, // E │ ^^^^^^^^ - 7 │ 2.302585, // LN10 - 8 │ 0.693147, // LN2 + 7 │ 2.718_281, // E with separator + 8 │ 2.302585, // LN10 - i Use Math.E instead. + i Unsafe fix: Use Math.E instead. + + 4 4 │ + 5 5 │ const constants = [ + 6 │ - → 2.718281,·//·E + 6 │ + → Math.E,·//·E + 7 7 │ 2.718_281, // E with separator + 8 8 │ 2.302585, // LN10 ``` ``` -invalid.js:7:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:7:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. 5 │ const constants = [ 6 │ 2.718281, // E - > 7 │ 2.302585, // LN10 - │ ^^^^^^^^ - 8 │ 0.693147, // LN2 - 9 │ 0.434294, // LOG10E + > 7 │ 2.718_281, // E with separator + │ ^^^^^^^^^ + 8 │ 2.302585, // LN10 + 9 │ 0.693147, // LN2 - i Use Math.LN10 instead. + i Unsafe fix: Use Math.E instead. + + 5 5 │ const constants = [ + 6 6 │ 2.718281, // E + 7 │ - → 2.718_281,·//·E·with·separator + 7 │ + → Math.E,·//·E·with·separator + 8 8 │ 2.302585, // LN10 + 9 9 │ 0.693147, // LN2 ``` ``` -invalid.js:8:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:8:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. 6 │ 2.718281, // E - 7 │ 2.302585, // LN10 - > 8 │ 0.693147, // LN2 + 7 │ 2.718_281, // E with separator + > 8 │ 2.302585, // LN10 │ ^^^^^^^^ - 9 │ 0.434294, // LOG10E - 10 │ 1.442695, // LOG2E + 9 │ 0.693147, // LN2 + 10 │ 0.434294, // LOG10E + + i Unsafe fix: Use Math.LN10 instead. - i Use Math.LN2 instead. + 6 6 │ 2.718281, // E + 7 7 │ 2.718_281, // E with separator + 8 │ - → 2.302585,·//·LN10 + 8 │ + → Math.LN10,·//·LN10 + 9 9 │ 0.693147, // LN2 + 10 10 │ 0.434294, // LOG10E ``` ``` -invalid.js:9:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:9:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 7 │ 2.302585, // LN10 - 8 │ 0.693147, // LN2 - > 9 │ 0.434294, // LOG10E + 7 │ 2.718_281, // E with separator + 8 │ 2.302585, // LN10 + > 9 │ 0.693147, // LN2 │ ^^^^^^^^ - 10 │ 1.442695, // LOG2E - 11 │ 3.141592, // PI + 10 │ 0.434294, // LOG10E + 11 │ 1.442695, // LOG2E - i Use Math.LOG10E instead. + i Unsafe fix: Use Math.LN2 instead. + + 7 7 │ 2.718_281, // E with separator + 8 8 │ 2.302585, // LN10 + 9 │ - → 0.693147,·//·LN2 + 9 │ + → Math.LN2,·//·LN2 + 10 10 │ 0.434294, // LOG10E + 11 11 │ 1.442695, // LOG2E ``` ``` -invalid.js:10:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:10:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 8 │ 0.693147, // LN2 - 9 │ 0.434294, // LOG10E - > 10 │ 1.442695, // LOG2E + 8 │ 2.302585, // LN10 + 9 │ 0.693147, // LN2 + > 10 │ 0.434294, // LOG10E │ ^^^^^^^^ - 11 │ 3.141592, // PI - 12 │ 0.707106, // SQRT1_2 + 11 │ 1.442695, // LOG2E + 12 │ 3.141592, // PI + + i Unsafe fix: Use Math.LOG10E instead. - i Use Math.LOG2E instead. + 8 8 │ 2.302585, // LN10 + 9 9 │ 0.693147, // LN2 + 10 │ - → 0.434294,·//·LOG10E + 10 │ + → Math.LOG10E,·//·LOG10E + 11 11 │ 1.442695, // LOG2E + 12 12 │ 3.141592, // PI ``` ``` -invalid.js:11:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:11:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 9 │ 0.434294, // LOG10E - 10 │ 1.442695, // LOG2E - > 11 │ 3.141592, // PI + 9 │ 0.693147, // LN2 + 10 │ 0.434294, // LOG10E + > 11 │ 1.442695, // LOG2E │ ^^^^^^^^ - 12 │ 0.707106, // SQRT1_2 - 13 │ 1.414213, // SQRT2 + 12 │ 3.141592, // PI + 13 │ 0.707106, // SQRT1_2 - i Use Math.PI instead. + i Unsafe fix: Use Math.LOG2E instead. + + 9 9 │ 0.693147, // LN2 + 10 10 │ 0.434294, // LOG10E + 11 │ - → 1.442695,·//·LOG2E + 11 │ + → Math.LOG2E,·//·LOG2E + 12 12 │ 3.141592, // PI + 13 13 │ 0.707106, // SQRT1_2 ``` ``` -invalid.js:12:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:12:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 10 │ 1.442695, // LOG2E - 11 │ 3.141592, // PI - > 12 │ 0.707106, // SQRT1_2 + 10 │ 0.434294, // LOG10E + 11 │ 1.442695, // LOG2E + > 12 │ 3.141592, // PI │ ^^^^^^^^ - 13 │ 1.414213, // SQRT2 - 14 │ ]; + 13 │ 0.707106, // SQRT1_2 + 14 │ 1.414213, // SQRT2 + + i Unsafe fix: Use Math.PI instead. - i Use Math.SQRT1_2 instead. + 10 10 │ 0.434294, // LOG10E + 11 11 │ 1.442695, // LOG2E + 12 │ - → 3.141592,·//·PI + 12 │ + → Math.PI,·//·PI + 13 13 │ 0.707106, // SQRT1_2 + 14 14 │ 1.414213, // SQRT2 ``` ``` -invalid.js:13:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:13:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 11 │ 3.141592, // PI - 12 │ 0.707106, // SQRT1_2 - > 13 │ 1.414213, // SQRT2 + 11 │ 1.442695, // LOG2E + 12 │ 3.141592, // PI + > 13 │ 0.707106, // SQRT1_2 │ ^^^^^^^^ - 14 │ ]; - 15 │ + 14 │ 1.414213, // SQRT2 + 15 │ ]; - i Use Math.SQRT2 instead. + i Unsafe fix: Use Math.SQRT1_2 instead. + + 11 11 │ 1.442695, // LOG2E + 12 12 │ 3.141592, // PI + 13 │ - → 0.707106,·//·SQRT1_2 + 13 │ + → Math.SQRT1_2,·//·SQRT1_2 + 14 14 │ 1.414213, // SQRT2 + 15 15 │ ]; + + +``` + +``` +invalid.js:14:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 12 │ 3.141592, // PI + 13 │ 0.707106, // SQRT1_2 + > 14 │ 1.414213, // SQRT2 + │ ^^^^^^^^ + 15 │ ]; + 16 │ + + i Unsafe fix: Use Math.SQRT2 instead. + + 12 12 │ 3.141592, // PI + 13 13 │ 0.707106, // SQRT1_2 + 14 │ - → 1.414213,·//·SQRT2 + 14 │ + → Math.SQRT2,·//·SQRT2 + 15 15 │ ]; + 16 16 │ ``` ``` -invalid.js:17:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:18:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 16 │ const constants1 = [ - > 17 │ 2.718, // E + 17 │ const constants1 = [ + > 18 │ 2.718, // E │ ^^^^^ - 18 │ 2.302, // LN10 - 19 │ 0.693, // LN2 + 19 │ 2.302, // LN10 + 20 │ 0.693, // LN2 - i Use Math.E instead. + i Unsafe fix: Use Math.E instead. + + 16 16 │ + 17 17 │ const constants1 = [ + 18 │ - → 2.718,·//·E + 18 │ + → Math.E,·//·E + 19 19 │ 2.302, // LN10 + 20 20 │ 0.693, // LN2 ``` ``` -invalid.js:18:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:19:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 16 │ const constants1 = [ - 17 │ 2.718, // E - > 18 │ 2.302, // LN10 + 17 │ const constants1 = [ + 18 │ 2.718, // E + > 19 │ 2.302, // LN10 │ ^^^^^ - 19 │ 0.693, // LN2 - 20 │ 0.434, // LOG10E + 20 │ 0.693, // LN2 + 21 │ 0.434, // LOG10E + + i Unsafe fix: Use Math.LN10 instead. - i Use Math.LN10 instead. + 17 17 │ const constants1 = [ + 18 18 │ 2.718, // E + 19 │ - → 2.302,·//·LN10 + 19 │ + → Math.LN10,·//·LN10 + 20 20 │ 0.693, // LN2 + 21 21 │ 0.434, // LOG10E ``` ``` -invalid.js:19:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:20:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 17 │ 2.718, // E - 18 │ 2.302, // LN10 - > 19 │ 0.693, // LN2 + 18 │ 2.718, // E + 19 │ 2.302, // LN10 + > 20 │ 0.693, // LN2 │ ^^^^^ - 20 │ 0.434, // LOG10E - 21 │ 1.442, // LOG2E + 21 │ 0.434, // LOG10E + 22 │ 1.442, // LOG2E - i Use Math.LN2 instead. + i Unsafe fix: Use Math.LN2 instead. + + 18 18 │ 2.718, // E + 19 19 │ 2.302, // LN10 + 20 │ - → 0.693,·//·LN2 + 20 │ + → Math.LN2,·//·LN2 + 21 21 │ 0.434, // LOG10E + 22 22 │ 1.442, // LOG2E ``` ``` -invalid.js:20:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:21:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 18 │ 2.302, // LN10 - 19 │ 0.693, // LN2 - > 20 │ 0.434, // LOG10E + 19 │ 2.302, // LN10 + 20 │ 0.693, // LN2 + > 21 │ 0.434, // LOG10E │ ^^^^^ - 21 │ 1.442, // LOG2E - 22 │ 3.141, // PI + 22 │ 1.442, // LOG2E + 23 │ 3.141, // PI + + i Unsafe fix: Use Math.LOG10E instead. - i Use Math.LOG10E instead. + 19 19 │ 2.302, // LN10 + 20 20 │ 0.693, // LN2 + 21 │ - → 0.434,·//·LOG10E + 21 │ + → Math.LOG10E,·//·LOG10E + 22 22 │ 1.442, // LOG2E + 23 23 │ 3.141, // PI ``` ``` -invalid.js:21:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:22:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 19 │ 0.693, // LN2 - 20 │ 0.434, // LOG10E - > 21 │ 1.442, // LOG2E + 20 │ 0.693, // LN2 + 21 │ 0.434, // LOG10E + > 22 │ 1.442, // LOG2E │ ^^^^^ - 22 │ 3.141, // PI - 23 │ 0.707, // SQRT1_2 + 23 │ 3.141, // PI + 24 │ 0.707, // SQRT1_2 - i Use Math.LOG2E instead. + i Unsafe fix: Use Math.LOG2E instead. + + 20 20 │ 0.693, // LN2 + 21 21 │ 0.434, // LOG10E + 22 │ - → 1.442,·//·LOG2E + 22 │ + → Math.LOG2E,·//·LOG2E + 23 23 │ 3.141, // PI + 24 24 │ 0.707, // SQRT1_2 ``` ``` -invalid.js:22:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:23:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 20 │ 0.434, // LOG10E - 21 │ 1.442, // LOG2E - > 22 │ 3.141, // PI + 21 │ 0.434, // LOG10E + 22 │ 1.442, // LOG2E + > 23 │ 3.141, // PI │ ^^^^^ - 23 │ 0.707, // SQRT1_2 - 24 │ 1.414, // SQRT2 + 24 │ 0.707, // SQRT1_2 + 25 │ 1.414, // SQRT2 + + i Unsafe fix: Use Math.PI instead. - i Use Math.PI instead. + 21 21 │ 0.434, // LOG10E + 22 22 │ 1.442, // LOG2E + 23 │ - → 3.141,·//·PI + 23 │ + → Math.PI,·//·PI + 24 24 │ 0.707, // SQRT1_2 + 25 25 │ 1.414, // SQRT2 ``` ``` -invalid.js:23:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:24:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 21 │ 1.442, // LOG2E - 22 │ 3.141, // PI - > 23 │ 0.707, // SQRT1_2 + 22 │ 1.442, // LOG2E + 23 │ 3.141, // PI + > 24 │ 0.707, // SQRT1_2 │ ^^^^^ - 24 │ 1.414, // SQRT2 - 25 │ ]; + 25 │ 1.414, // SQRT2 + 26 │ ]; - i Use Math.SQRT1_2 instead. + i Unsafe fix: Use Math.SQRT1_2 instead. + + 22 22 │ 1.442, // LOG2E + 23 23 │ 3.141, // PI + 24 │ - → 0.707,·//·SQRT1_2 + 24 │ + → Math.SQRT1_2,·//·SQRT1_2 + 25 25 │ 1.414, // SQRT2 + 26 26 │ ]; ``` ``` -invalid.js:24:2 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +invalid.js:25:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ ! Prefer constants from the standard library. - 22 │ 3.141, // PI - 23 │ 0.707, // SQRT1_2 - > 24 │ 1.414, // SQRT2 + 23 │ 3.141, // PI + 24 │ 0.707, // SQRT1_2 + > 25 │ 1.414, // SQRT2 │ ^^^^^ - 25 │ ]; - 26 │ + 26 │ ]; + 27 │ + + i Unsafe fix: Use Math.SQRT2 instead. + + 23 23 │ 3.141, // PI + 24 24 │ 0.707, // SQRT1_2 + 25 │ - → 1.414,·//·SQRT2 + 25 │ + → Math.SQRT2,·//·SQRT2 + 26 26 │ ]; + 27 27 │ + + +``` + +``` +invalid.js:29:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 28 │ const exact = [ + > 29 │ 2.718281828459045, // E + │ ^^^^^^^^^^^^^^^^^ + 30 │ 2.302585092994046, // LN10 + 31 │ 0.6931471805599453, // LN2 + + i Unsafe fix: Use Math.E instead. + + 27 27 │ + 28 28 │ const exact = [ + 29 │ - → 2.718281828459045,·//·E + 29 │ + → Math.E,·//·E + 30 30 │ 2.302585092994046, // LN10 + 31 31 │ 0.6931471805599453, // LN2 + + +``` + +``` +invalid.js:30:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 28 │ const exact = [ + 29 │ 2.718281828459045, // E + > 30 │ 2.302585092994046, // LN10 + │ ^^^^^^^^^^^^^^^^^ + 31 │ 0.6931471805599453, // LN2 + 32 │ 0.4342944819032518, // LOG10E + + i Unsafe fix: Use Math.LN10 instead. + + 28 28 │ const exact = [ + 29 29 │ 2.718281828459045, // E + 30 │ - ····2.302585092994046,·//·LN10 + 30 │ + ····Math.LN10,·//·LN10 + 31 31 │ 0.6931471805599453, // LN2 + 32 32 │ 0.4342944819032518, // LOG10E + + +``` + +``` +invalid.js:31:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 29 │ 2.718281828459045, // E + 30 │ 2.302585092994046, // LN10 + > 31 │ 0.6931471805599453, // LN2 + │ ^^^^^^^^^^^^^^^^^^ + 32 │ 0.4342944819032518, // LOG10E + 33 │ 1.4426950408889634, // LOG2E + + i Unsafe fix: Use Math.LN2 instead. + + 29 29 │ 2.718281828459045, // E + 30 30 │ 2.302585092994046, // LN10 + 31 │ - ····0.6931471805599453,·//·LN2 + 31 │ + ····Math.LN2,·//·LN2 + 32 32 │ 0.4342944819032518, // LOG10E + 33 33 │ 1.4426950408889634, // LOG2E + + +``` + +``` +invalid.js:32:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 30 │ 2.302585092994046, // LN10 + 31 │ 0.6931471805599453, // LN2 + > 32 │ 0.4342944819032518, // LOG10E + │ ^^^^^^^^^^^^^^^^^^ + 33 │ 1.4426950408889634, // LOG2E + 34 │ 3.141592653589793, // PI + + i Unsafe fix: Use Math.LOG10E instead. + + 30 30 │ 2.302585092994046, // LN10 + 31 31 │ 0.6931471805599453, // LN2 + 32 │ - ····0.4342944819032518,·//·LOG10E + 32 │ + ····Math.LOG10E,·//·LOG10E + 33 33 │ 1.4426950408889634, // LOG2E + 34 34 │ 3.141592653589793, // PI + + +``` + +``` +invalid.js:33:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 31 │ 0.6931471805599453, // LN2 + 32 │ 0.4342944819032518, // LOG10E + > 33 │ 1.4426950408889634, // LOG2E + │ ^^^^^^^^^^^^^^^^^^ + 34 │ 3.141592653589793, // PI + 35 │ 0.7071067811865476, // SQRT1_2 + + i Unsafe fix: Use Math.LOG2E instead. + + 31 31 │ 0.6931471805599453, // LN2 + 32 32 │ 0.4342944819032518, // LOG10E + 33 │ - ····1.4426950408889634,·//·LOG2E + 33 │ + ····Math.LOG2E,·//·LOG2E + 34 34 │ 3.141592653589793, // PI + 35 35 │ 0.7071067811865476, // SQRT1_2 + + +``` + +``` +invalid.js:34:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 32 │ 0.4342944819032518, // LOG10E + 33 │ 1.4426950408889634, // LOG2E + > 34 │ 3.141592653589793, // PI + │ ^^^^^^^^^^^^^^^^^ + 35 │ 0.7071067811865476, // SQRT1_2 + 36 │ .7071067811865476, // SQRT1_2 without leading 0 + + i Unsafe fix: Use Math.PI instead. + + 32 32 │ 0.4342944819032518, // LOG10E + 33 33 │ 1.4426950408889634, // LOG2E + 34 │ - ····3.141592653589793,·//·PI + 34 │ + ····Math.PI,·//·PI + 35 35 │ 0.7071067811865476, // SQRT1_2 + 36 36 │ .7071067811865476, // SQRT1_2 without leading 0 + + +``` + +``` +invalid.js:35:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 33 │ 1.4426950408889634, // LOG2E + 34 │ 3.141592653589793, // PI + > 35 │ 0.7071067811865476, // SQRT1_2 + │ ^^^^^^^^^^^^^^^^^^ + 36 │ .7071067811865476, // SQRT1_2 without leading 0 + 37 │ 1.4142135623730951, // SQRT2 + + i Unsafe fix: Use Math.SQRT1_2 instead. + + 33 33 │ 1.4426950408889634, // LOG2E + 34 34 │ 3.141592653589793, // PI + 35 │ - ····0.7071067811865476,·//·SQRT1_2 + 35 │ + ····Math.SQRT1_2,·//·SQRT1_2 + 36 36 │ .7071067811865476, // SQRT1_2 without leading 0 + 37 37 │ 1.4142135623730951, // SQRT2 + + +``` + +``` +invalid.js:36:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 34 │ 3.141592653589793, // PI + 35 │ 0.7071067811865476, // SQRT1_2 + > 36 │ .7071067811865476, // SQRT1_2 without leading 0 + │ ^^^^^^^^^^^^^^^^^ + 37 │ 1.4142135623730951, // SQRT2 + 38 │ ]; + + i Unsafe fix: Use Math.SQRT1_2 instead. + + 34 34 │ 3.141592653589793, // PI + 35 35 │ 0.7071067811865476, // SQRT1_2 + 36 │ - ····.7071067811865476,·//·SQRT1_2·without·leading·0 + 36 │ + ····Math.SQRT1_2,·//·SQRT1_2·without·leading·0 + 37 37 │ 1.4142135623730951, // SQRT2 + 38 38 │ ]; + + +``` + +``` +invalid.js:37:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 35 │ 0.7071067811865476, // SQRT1_2 + 36 │ .7071067811865476, // SQRT1_2 without leading 0 + > 37 │ 1.4142135623730951, // SQRT2 + │ ^^^^^^^^^^^^^^^^^^ + 38 │ ]; + 39 │ + + i Unsafe fix: Use Math.SQRT2 instead. + + 35 35 │ 0.7071067811865476, // SQRT1_2 + 36 36 │ .7071067811865476, // SQRT1_2 without leading 0 + 37 │ - ····1.4142135623730951,·//·SQRT2 + 37 │ + ····Math.SQRT2,·//·SQRT2 + 38 38 │ ]; + 39 39 │ + + +``` + +``` +invalid.js:42:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 40 │ const rounded = [ + 41 │ // rounded + > 42 │ 2.7183, // E + │ ^^^^^^ + 43 │ 2.302585093, // LN10 + 44 │ 0.6931471806, // LN2 + + i Unsafe fix: Use Math.E instead. + + 40 40 │ const rounded = [ + 41 41 │ // rounded + 42 │ - → 2.7183,·//·E + 42 │ + → Math.E,·//·E + 43 43 │ 2.302585093, // LN10 + 44 44 │ 0.6931471806, // LN2 + + +``` + +``` +invalid.js:43:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 41 │ // rounded + 42 │ 2.7183, // E + > 43 │ 2.302585093, // LN10 + │ ^^^^^^^^^^^ + 44 │ 0.6931471806, // LN2 + 45 │ 0.4342944819033, // LOG10E + + i Unsafe fix: Use Math.LN10 instead. + + 41 41 │ // rounded + 42 42 │ 2.7183, // E + 43 │ - ····2.302585093,·//·LN10 + 43 │ + ····Math.LN10,·//·LN10 + 44 44 │ 0.6931471806, // LN2 + 45 45 │ 0.4342944819033, // LOG10E + + +``` + +``` +invalid.js:44:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 42 │ 2.7183, // E + 43 │ 2.302585093, // LN10 + > 44 │ 0.6931471806, // LN2 + │ ^^^^^^^^^^^^ + 45 │ 0.4342944819033, // LOG10E + 46 │ 1.442695040889, // LOG2E + + i Unsafe fix: Use Math.LN2 instead. + + 42 42 │ 2.7183, // E + 43 43 │ 2.302585093, // LN10 + 44 │ - ····0.6931471806,·//·LN2 + 44 │ + ····Math.LN2,·//·LN2 + 45 45 │ 0.4342944819033, // LOG10E + 46 46 │ 1.442695040889, // LOG2E + + +``` + +``` +invalid.js:45:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 43 │ 2.302585093, // LN10 + 44 │ 0.6931471806, // LN2 + > 45 │ 0.4342944819033, // LOG10E + │ ^^^^^^^^^^^^^^^ + 46 │ 1.442695040889, // LOG2E + 47 │ 3.1415926535898, // PI + + i Unsafe fix: Use Math.LOG10E instead. + + 43 43 │ 2.302585093, // LN10 + 44 44 │ 0.6931471806, // LN2 + 45 │ - ····0.4342944819033,·//·LOG10E + 45 │ + ····Math.LOG10E,·//·LOG10E + 46 46 │ 1.442695040889, // LOG2E + 47 47 │ 3.1415926535898, // PI + + +``` + +``` +invalid.js:46:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 44 │ 0.6931471806, // LN2 + 45 │ 0.4342944819033, // LOG10E + > 46 │ 1.442695040889, // LOG2E + │ ^^^^^^^^^^^^^^ + 47 │ 3.1415926535898, // PI + 48 │ 0.70710678118655, // SQRT1_2 + + i Unsafe fix: Use Math.LOG2E instead. + + 44 44 │ 0.6931471806, // LN2 + 45 45 │ 0.4342944819033, // LOG10E + 46 │ - ····1.442695040889,·//·LOG2E + 46 │ + ····Math.LOG2E,·//·LOG2E + 47 47 │ 3.1415926535898, // PI + 48 48 │ 0.70710678118655, // SQRT1_2 + + +``` + +``` +invalid.js:47:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 45 │ 0.4342944819033, // LOG10E + 46 │ 1.442695040889, // LOG2E + > 47 │ 3.1415926535898, // PI + │ ^^^^^^^^^^^^^^^ + 48 │ 0.70710678118655, // SQRT1_2 + 49 │ 1.4142135623731, // SQRT2 + + i Unsafe fix: Use Math.PI instead. + + 45 45 │ 0.4342944819033, // LOG10E + 46 46 │ 1.442695040889, // LOG2E + 47 │ - ····3.1415926535898,·//·PI + 47 │ + ····Math.PI,·//·PI + 48 48 │ 0.70710678118655, // SQRT1_2 + 49 49 │ 1.4142135623731, // SQRT2 + + +``` + +``` +invalid.js:48:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 46 │ 1.442695040889, // LOG2E + 47 │ 3.1415926535898, // PI + > 48 │ 0.70710678118655, // SQRT1_2 + │ ^^^^^^^^^^^^^^^^ + 49 │ 1.4142135623731, // SQRT2 + 50 │ ]; + + i Unsafe fix: Use Math.SQRT1_2 instead. + + 46 46 │ 1.442695040889, // LOG2E + 47 47 │ 3.1415926535898, // PI + 48 │ - ····0.70710678118655,·//·SQRT1_2 + 48 │ + ····Math.SQRT1_2,·//·SQRT1_2 + 49 49 │ 1.4142135623731, // SQRT2 + 50 50 │ ]; + + +``` + +``` +invalid.js:49:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 47 │ 3.1415926535898, // PI + 48 │ 0.70710678118655, // SQRT1_2 + > 49 │ 1.4142135623731, // SQRT2 + │ ^^^^^^^^^^^^^^^ + 50 │ ]; + 51 │ + + i Unsafe fix: Use Math.SQRT2 instead. + + 47 47 │ 3.1415926535898, // PI + 48 48 │ 0.70710678118655, // SQRT1_2 + 49 │ - ····1.4142135623731,·//·SQRT2 + 49 │ + ····Math.SQRT2,·//·SQRT2 + 50 50 │ ]; + 51 51 │ + + +``` + +``` +invalid.js:53:2 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 52 │ const precisionLoss = [ + > 53 │ 2.71828182845904523536028747135266250, // E + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 54 │ 2.30258509299404568401799145468436421, // LN10 + 55 │ 0.693147180559945309417232121458176568, // LN2 + + i Unsafe fix: Use Math.E instead. + + 51 51 │ + 52 52 │ const precisionLoss = [ + 53 │ - → 2.71828182845904523536028747135266250,·//·E + 53 │ + → Math.E,·//·E + 54 54 │ 2.30258509299404568401799145468436421, // LN10 + 55 55 │ 0.693147180559945309417232121458176568, // LN2 + + +``` + +``` +invalid.js:54:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 52 │ const precisionLoss = [ + 53 │ 2.71828182845904523536028747135266250, // E + > 54 │ 2.30258509299404568401799145468436421, // LN10 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 55 │ 0.693147180559945309417232121458176568, // LN2 + 56 │ 0.301029995663981195213738894724493027, // LOG10E + + i Unsafe fix: Use Math.LN10 instead. + + 52 52 │ const precisionLoss = [ + 53 53 │ 2.71828182845904523536028747135266250, // E + 54 │ - ····2.30258509299404568401799145468436421,·//·LN10 + 54 │ + ····Math.LN10,·//·LN10 + 55 55 │ 0.693147180559945309417232121458176568, // LN2 + 56 56 │ 0.301029995663981195213738894724493027, // LOG10E + + +``` + +``` +invalid.js:55:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 53 │ 2.71828182845904523536028747135266250, // E + 54 │ 2.30258509299404568401799145468436421, // LN10 + > 55 │ 0.693147180559945309417232121458176568, // LN2 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 56 │ 0.301029995663981195213738894724493027, // LOG10E + 57 │ 1.44269504088896340735992468100189214, // LOG2E + + i Unsafe fix: Use Math.LN2 instead. + + 53 53 │ 2.71828182845904523536028747135266250, // E + 54 54 │ 2.30258509299404568401799145468436421, // LN10 + 55 │ - ····0.693147180559945309417232121458176568,·//·LN2 + 55 │ + ····Math.LN2,·//·LN2 + 56 56 │ 0.301029995663981195213738894724493027, // LOG10E + 57 57 │ 1.44269504088896340735992468100189214, // LOG2E + + +``` + +``` +invalid.js:57:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 55 │ 0.693147180559945309417232121458176568, // LN2 + 56 │ 0.301029995663981195213738894724493027, // LOG10E + > 57 │ 1.44269504088896340735992468100189214, // LOG2E + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 58 │ 3.14159265358979323846264338327950288, // PI + 59 │ 0.707106781186547524400844362104849039, // SQRT1_2 + + i Unsafe fix: Use Math.LOG2E instead. + + 55 55 │ 0.693147180559945309417232121458176568, // LN2 + 56 56 │ 0.301029995663981195213738894724493027, // LOG10E + 57 │ - ····1.44269504088896340735992468100189214,·//·LOG2E + 57 │ + ····Math.LOG2E,·//·LOG2E + 58 58 │ 3.14159265358979323846264338327950288, // PI + 59 59 │ 0.707106781186547524400844362104849039, // SQRT1_2 + + +``` + +``` +invalid.js:58:5 lint/suspicious/noApproximativeNumericConstant FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + ! Prefer constants from the standard library. + + 56 │ 0.301029995663981195213738894724493027, // LOG10E + 57 │ 1.44269504088896340735992468100189214, // LOG2E + > 58 │ 3.14159265358979323846264338327950288, // PI + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + 59 │ 0.707106781186547524400844362104849039, // SQRT1_2 + 60 │ 1.41421356237309504880168872420969808, // SQRT2 + + i Unsafe fix: Use Math.PI instead. - i Use Math.SQRT2 instead. + 56 56 │ 0.301029995663981195213738894724493027, // LOG10E + 57 57 │ 1.44269504088896340735992468100189214, // LOG2E + 58 │ - ····3.14159265358979323846264338327950288,·//·PI + 58 │ + ····Math.PI,·//·PI + 59 59 │ 0.707106781186547524400844362104849039, // SQRT1_2 + 60 60 │ 1.41421356237309504880168872420969808, // SQRT2 ``` diff --git a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js index 008669e4169e..c12dde169f02 100644 --- a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js +++ b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js @@ -3,3 +3,14 @@ const y = Math.LN10; const z = 2.301; const w = 2.304; const piOk = 3.14; + +const tooMuchRounded = [ + 2.7184, // E + 2.302585094, // LN10 + 0.6931471807, // LN2 + 0.4342944819034, // LOG10E + 1.442695042, // LOG2E + 3.1415926537, // PI + 0.7071067813, // SQRT1_2 + 1.4142135625, // SQRT2 +]; diff --git a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js.snap b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js.snap index c0dbaa14294c..d9c10e3a0ac0 100644 --- a/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js.snap +++ b/crates/biome_js_analyze/tests/specs/suspicious/noApproximativeNumericConstant/valid.js.snap @@ -10,6 +10,17 @@ const z = 2.301; const w = 2.304; const piOk = 3.14; +const tooMuchRounded = [ + 2.7184, // E + 2.302585094, // LN10 + 0.6931471807, // LN2 + 0.4342944819034, // LOG10E + 1.442695042, // LOG2E + 3.1415926537, // PI + 0.7071067813, // SQRT1_2 + 1.4142135625, // SQRT2 +]; + ``` diff --git a/crates/biome_js_syntax/src/numbers.rs b/crates/biome_js_syntax/src/numbers.rs index d392992dd56e..6506d28fd928 100644 --- a/crates/biome_js_syntax/src/numbers.rs +++ b/crates/biome_js_syntax/src/numbers.rs @@ -1,17 +1,21 @@ //! JS Number parsing. -use std::str::FromStr; +use std::{borrow::Cow, str::FromStr}; /// Split given string into radix and number string. /// /// It also removes any underscores. -pub fn split_into_radix_and_number(num: &str) -> (u32, String) { +pub fn split_into_radix_and_number(num: &str) -> (u8, Cow) { let (radix, raw) = parse_js_number_prefix(num).unwrap_or((10, num)); - let raw = raw.replace('_', ""); + let raw = if raw.contains('_') { + Cow::Owned(raw.replace('_', "")) + } else { + Cow::Borrowed(raw) + }; (radix, raw) } -fn parse_js_number_prefix(num: &str) -> Option<(u32, &str)> { +fn parse_js_number_prefix(num: &str) -> Option<(u8, &str)> { let mut chars = num.chars(); let c = chars.next()?; if c != '0' { @@ -34,7 +38,9 @@ pub fn parse_js_number(num: &str) -> Option { if radix == 10 { f64::from_str(&raw).ok() } else { - i64::from_str_radix(&raw, radix).map(|num| num as f64).ok() + i64::from_str_radix(&raw, radix as u32) + .map(|num| num as f64) + .ok() } } @@ -95,7 +101,7 @@ mod tests { assert_float("058", 58.0); } - fn assert_split(raw: &str, expected_radix: u32, expected_num: &str) { + fn assert_split(raw: &str, expected_radix: u8, expected_num: &str) { let (radix, num) = split_into_radix_and_number(raw); assert_eq!(radix, expected_radix); assert_eq!(num, expected_num); diff --git a/crates/biome_service/src/configuration/linter/rules.rs b/crates/biome_service/src/configuration/linter/rules.rs index 90f5b3170622..cbfcd0b4d2d9 100644 --- a/crates/biome_service/src/configuration/linter/rules.rs +++ b/crates/biome_service/src/configuration/linter/rules.rs @@ -3695,7 +3695,7 @@ pub struct Suspicious { #[doc = r" It enables ALL rules for this group."] #[serde(skip_serializing_if = "Option::is_none")] pub all: Option, - #[doc = "Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type."] + #[doc = "Use standard constants instead of approximated literals."] #[serde(skip_serializing_if = "Option::is_none")] pub no_approximative_numeric_constant: Option, #[doc = "Discourage the usage of Array index in keys."] diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts index 8ac63316784b..7c707d35b42d 100644 --- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts +++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts @@ -1163,7 +1163,7 @@ export interface Suspicious { */ all?: boolean; /** - * Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type. + * Use standard constants instead of approximated literals. */ noApproximativeNumericConstant?: RuleConfiguration; /** diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json index 619e15453d48..07fc66013231 100644 --- a/packages/@biomejs/biome/configuration_schema.json +++ b/packages/@biomejs/biome/configuration_schema.json @@ -2049,7 +2049,7 @@ "type": ["boolean", "null"] }, "noApproximativeNumericConstant": { - "description": "Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type.", + "description": "Use standard constants instead of approximated literals.", "anyOf": [ { "$ref": "#/definitions/RuleConfiguration" }, { "type": "null" } diff --git a/website/src/content/docs/internals/changelog.mdx b/website/src/content/docs/internals/changelog.mdx index 94b8d190c166..4259c82bbc05 100644 --- a/website/src/content/docs/internals/changelog.mdx +++ b/website/src/content/docs/internals/changelog.mdx @@ -65,10 +65,6 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom ### Linter -#### Enhancements - -- [noUselessTernary](https://biomejs.dev/linter/rules/no-useless-ternary/) now provides unsafe code fixes. Contributed by @vasucp1207 - #### New features - Add the rule [noSkippedTests](https://biomejs.dev/linter/rules/no-skipped-tests), to disallow skipped tests: @@ -95,6 +91,32 @@ Read our [guidelines for writing a good changelog entry](https://github.com/biom ``` Contributed by @DaniGuardiola +#### Enhancements + +- [noUselessTernary](https://biomejs.dev/linter/rules/no-useless-ternary) now provides unsafe code fixes. Contributed by @vasucp1207 + +- [noApproximativeNumericConstant](https://biomejs.dev/linter/rules/no-approximative-numeric-constant) now provides unsafe code fixes and handle numbers without leading zero and numbers with digit separators. + + The following numbers are now reported as approximated constants. + + ```js + 3.14_15; // PI + .4342; // LOG10E + ``` + + Contributed by @Conaclos + +- [noPrecisionLoss](https://biomejs.dev/linter/rules/no-precision-loss) no longer reports number with extra zeros. + + The following numbers are now valid. + + ```js + .1230000000000000000000000; + 1230000000000000000000000.0; + ``` + + Contributed by @Conaclos + #### Bug fixes - Fix [#1651](https://github.com/biomejs/biome/issues/1651). [noVar](https://biomejs.dev/linter/rules/no-var/) now ignores TsGlobalDeclaration. Contributed by @vasucp1207 diff --git a/website/src/content/docs/linter/rules/index.mdx b/website/src/content/docs/linter/rules/index.mdx index a47e33bfe666..550aa76a4470 100644 --- a/website/src/content/docs/linter/rules/index.mdx +++ b/website/src/content/docs/linter/rules/index.mdx @@ -174,7 +174,7 @@ Rules enforcing a consistent and idiomatic way of writing your code. Rules that detect code that is likely to be incorrect or useless. | Rule name | Description | Properties | | --- | --- | --- | -| [noApproximativeNumericConstant](/linter/rules/no-approximative-numeric-constant) | Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type. | | +| [noApproximativeNumericConstant](/linter/rules/no-approximative-numeric-constant) | Use standard constants instead of approximated literals. | ⚠️ | | [noArrayIndexKey](/linter/rules/no-array-index-key) | Discourage the usage of Array index in keys. | | | [noAssignInExpressions](/linter/rules/no-assign-in-expressions) | Disallow assignments in expressions. | | | [noAsyncPromiseExecutor](/linter/rules/no-async-promise-executor) | Disallows using an async function as a Promise executor. | | diff --git a/website/src/content/docs/linter/rules/no-approximative-numeric-constant.md b/website/src/content/docs/linter/rules/no-approximative-numeric-constant.md index 91b8bb6de7e3..ea49b5cc28b0 100644 --- a/website/src/content/docs/linter/rules/no-approximative-numeric-constant.md +++ b/website/src/content/docs/linter/rules/no-approximative-numeric-constant.md @@ -6,7 +6,10 @@ title: noApproximativeNumericConstant (since v1.3.0) Source: approx_constant -Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type. +Use standard constants instead of approximated literals. + +Usually, the definition in the standard library is more precise than +what people come up with or the used constant exceeds the maximum precision of the number type. ## Examples @@ -16,7 +19,7 @@ Usually, the definition in the standard library is more precise than what people let x = 3.141; ``` -
suspicious/noApproximativeNumericConstant.js:1:9 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━
+
suspicious/noApproximativeNumericConstant.js:1:9 lint/suspicious/noApproximativeNumericConstant  FIXABLE  ━━━━━━━━━━
 
    Prefer constants from the standard library.
   
@@ -24,7 +27,11 @@ let x = 3.141;
            ^^^^^
     2 │ 
   
-   Use Math.PI instead.
+   Unsafe fix: Use Math.PI instead.
+  
+    1  - let·x·=·3.141;
+      1+ let·x·=·Math.PI;
+    2 2  
   
 
@@ -32,7 +39,7 @@ let x = 3.141; let x = 2.302; ``` -
suspicious/noApproximativeNumericConstant.js:1:9 lint/suspicious/noApproximativeNumericConstant ━━━━━━━━━━
+
suspicious/noApproximativeNumericConstant.js:1:9 lint/suspicious/noApproximativeNumericConstant  FIXABLE  ━━━━━━━━━━
 
    Prefer constants from the standard library.
   
@@ -40,7 +47,11 @@ let x = 2.302;
            ^^^^^
     2 │ 
   
-   Use Math.LN10 instead.
+   Unsafe fix: Use Math.LN10 instead.
+  
+    1  - let·x·=·2.302;
+      1+ let·x·=·Math.LN10;
+    2 2  
   
 
@@ -48,6 +59,7 @@ let x = 2.302; ```jsx let x = Math.PI; +let y = 3.14; ``` ```jsx diff --git a/website/src/content/docs/linter/rules/no-precision-loss.md b/website/src/content/docs/linter/rules/no-precision-loss.md index 790caa55a093..da344962998e 100644 --- a/website/src/content/docs/linter/rules/no-precision-loss.md +++ b/website/src/content/docs/linter/rules/no-precision-loss.md @@ -33,62 +33,30 @@ const x = 9007199254740993
```jsx -const x = 5123000000000000000000000000001 +const x = 5.123000000000000000000000000001 ```
correctness/noPrecisionLoss.js:1:11 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
    This number literal will lose precision at runtime.
   
-  > 1 │ const x = 5123000000000000000000000000001
-             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  > 1 │ const x = 5.123000000000000000000000000001
+             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     2 │ 
   
-   The value at runtime will be 5123000000000000000000000000000
+   The value at runtime will be 5.123
   
 
```jsx -const x = 1230000000000000000000000.0 +const x = 0x20000000000001 ```
correctness/noPrecisionLoss.js:1:11 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
    This number literal will lose precision at runtime.
   
-  > 1 │ const x = 1230000000000000000000000.0
-             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    2 │ 
-  
-   The value at runtime will be 1230000000000000000000000
-  
-
- -```jsx -const x = .1230000000000000000000000 -``` - -
correctness/noPrecisionLoss.js:1:11 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
-   This number literal will lose precision at runtime.
-  
-  > 1 │ const x = .1230000000000000000000000
-             ^^^^^^^^^^^^^^^^^^^^^^^^^^
-    2 │ 
-  
-   The value at runtime will be 0.123
-  
-
- -```jsx -const x = 0X20000000000001 -``` - -
correctness/noPrecisionLoss.js:1:11 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-
-   This number literal will lose precision at runtime.
-  
-  > 1 │ const x = 0X20000000000001
+  > 1 │ const x = 0x20000000000001
              ^^^^^^^^^^^^^^^^
     2 │ 
   
@@ -97,14 +65,14 @@ const x = 0X20000000000001
 
```jsx -const x = 0X2_000000000_0001; +const x = 0x2_000000000_0001; ```
correctness/noPrecisionLoss.js:1:11 lint/correctness/noPrecisionLoss ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 
    This number literal will lose precision at runtime.
   
-  > 1 │ const x = 0X2_000000000_0001;
+  > 1 │ const x = 0x2_000000000_0001;
              ^^^^^^^^^^^^^^^^^^
     2 │