feat(linter): eslint-plugin-unicorn numeric-separators-style (style) (#1490)

Part of #684.
This commit is contained in:
Jon Surrell 2023-11-30 08:58:46 +01:00 committed by GitHub
parent 6ec257ba2d
commit 8bef1f1964
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 958 additions and 0 deletions

View file

@ -179,6 +179,7 @@ mod unicorn {
pub mod no_useless_switch_case;
pub mod no_zero_fractions;
pub mod number_literal_case;
pub mod numeric_separators_style;
pub mod prefer_add_event_listener;
pub mod prefer_array_flat_map;
pub mod prefer_array_some;
@ -357,6 +358,7 @@ oxc_macros::declare_all_lint_rules! {
unicorn::no_useless_switch_case,
unicorn::no_zero_fractions,
unicorn::number_literal_case,
unicorn::numeric_separators_style,
unicorn::prefer_add_event_listener,
unicorn::prefer_array_flat_map,
unicorn::prefer_blob_reading_methods,

View file

@ -0,0 +1,671 @@
use lazy_static::lazy_static;
use oxc_ast::{
ast::{BigintLiteral, NumberLiteral},
AstKind,
};
use oxc_diagnostics::{
miette::{self, Diagnostic},
thiserror::Error,
};
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use regex::Regex;
use crate::{context::LintContext, fixer::Fix, rule::Rule, AstNode};
#[derive(Debug, Error, Diagnostic)]
#[error("eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.")]
#[diagnostic(
severity(warning),
help("Group digits with numeric separators (_) so longer numbers are easier to read.")
)]
struct NumericSeparatorsStyleDiagnostic(#[label] pub Span);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NumericSeparatorsStyle {
only_if_contains_separator: bool,
hexadecimal: NumericBaseConfig,
binary: NumericBaseConfig,
octal: NumericBaseConfig,
number: NumericBaseConfig,
}
impl Default for NumericSeparatorsStyle {
fn default() -> Self {
Self {
only_if_contains_separator: false,
binary: NumericBaseConfig { group_length: 4, minimum_digits: 0 },
hexadecimal: NumericBaseConfig { group_length: 2, minimum_digits: 0 },
number: NumericBaseConfig { group_length: 3, minimum_digits: 5 },
octal: NumericBaseConfig { group_length: 4, minimum_digits: 0 },
}
}
}
declare_oxc_lint!(
/// ### What it does
/// Enforces a convention of grouping digits using numeric separators.
///
/// ### Why is this bad?
/// Long numbers can become really hard to read, so cutting it into groups of digits,
/// separated with a _, is important to keep your code clear. This rule also enforces
/// a proper usage of the numeric separator, by checking if the groups of digits are
/// of the correct size.
///
///
/// ### Example
/// ```javascript
/// const invalid = [
/// 1_23_4444,
/// 1_234.56789,
/// 0xAB_C_D_EF,
/// 0b10_00_1111,
/// 0o1_0_44_21,
/// 1_294_28771_2n,
/// ];
/// const valid = [
/// 1_234_567,
/// 1_234.567_89,
/// 0xAB_CD_EF,
/// 0b1000_1111,
/// 0o10_4421,
/// 1_294_287_712n,
/// ];
/// ```
NumericSeparatorsStyle,
style
);
impl Rule for NumericSeparatorsStyle {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
match node.kind() {
AstKind::NumberLiteral(number) => {
if self.only_if_contains_separator && !number.raw.contains('_') {
return;
}
let formatted = self.format_number(number);
if formatted != number.raw {
ctx.diagnostic_with_fix(NumericSeparatorsStyleDiagnostic(number.span), || {
Fix::new(formatted, number.span)
});
}
}
AstKind::BigintLiteral(number) => {
let raw = number.span.source_text(ctx.source_text());
if self.only_if_contains_separator && !raw.contains('_') {
return;
}
let formatted = self.format_bigint(number, raw);
if formatted.len() != number.span.size() as usize {
ctx.diagnostic_with_fix(NumericSeparatorsStyleDiagnostic(number.span), || {
Fix::new(formatted, number.span)
});
}
}
_ => {}
};
}
fn from_configuration(value: serde_json::Value) -> Self {
let mut cfg = Self::default();
if let Some(config) = value.get(0) {
if let Some(config) = config.get("binary") {
cfg.binary.set_numeric_base_from_config(config);
}
if let Some(config) = config.get("hexadecimal") {
cfg.hexadecimal.set_numeric_base_from_config(config);
}
if let Some(config) = config.get("number") {
cfg.number.set_numeric_base_from_config(config);
}
if let Some(config) = config.get("octal") {
cfg.octal.set_numeric_base_from_config(config);
}
if let Some(val) =
config.get("onlyIfContainsSeparator").and_then(serde_json::Value::as_bool)
{
cfg.only_if_contains_separator = val;
}
}
cfg
}
}
impl NumericSeparatorsStyle {
fn format_number(&self, number: &NumberLiteral) -> String {
use oxc_syntax::NumberBase;
match number.base {
NumberBase::Binary => self.format_binary(number.raw),
NumberBase::Decimal | oxc_syntax::NumberBase::Float => self.format_decimal(number.raw),
NumberBase::Hex => self.format_hex(number.raw),
NumberBase::Octal => self.format_octal(number.raw),
}
}
fn format_bigint(&self, number: &BigintLiteral, raw: &str) -> String {
use oxc_syntax::BigintBase;
let raw_without_bigint_n_suffix = &raw[..raw.len() - 1];
let mut formatted = match number.base {
BigintBase::Binary => self.format_binary(raw_without_bigint_n_suffix),
BigintBase::Decimal => self.format_decimal(raw_without_bigint_n_suffix),
BigintBase::Hex => self.format_hex(raw_without_bigint_n_suffix),
BigintBase::Octal => self.format_octal(raw_without_bigint_n_suffix),
};
formatted.push('n');
formatted
}
fn format_binary(&self, raw_number: &str) -> String {
let prefix = &raw_number[0..2];
let mut to_format = raw_number[2..].replace('_', "");
add_separators(&mut to_format, &SeparatorDir::Right, &self.binary);
to_format.insert_str(0, prefix);
to_format
}
fn format_hex(&self, number_raw: &str) -> String {
let prefix = &number_raw[0..2];
let mut to_format = number_raw[2..].replace('_', "");
add_separators(&mut to_format, &SeparatorDir::Right, &self.hexadecimal);
to_format.insert_str(0, prefix);
to_format
}
fn format_octal(&self, number_raw: &str) -> String {
// Legacy octal numbers are 0-prefixed, e.g. `010 === 8`.
// Legacy octal notation does not support `_` prefixes.
let is_legacy = number_raw.as_bytes()[1] != b'o' && number_raw.as_bytes()[1] != b'O';
if is_legacy {
return number_raw.to_string();
}
let prefix = &number_raw[0..2];
let mut to_format = number_raw[2..].replace('_', "");
add_separators(&mut to_format, &SeparatorDir::Right, &self.octal);
to_format.insert_str(0, prefix);
to_format
}
fn format_decimal(&self, number_raw: &str) -> String {
lazy_static! {
static ref NUMBER_REGEX: Regex =
Regex::new(r"^([\d._]*?)(?:([Ee])([+-])?([\d_]+))?$").unwrap();
}
let caps = NUMBER_REGEX.captures(number_raw).unwrap();
let mut out = String::new();
{
let number = caps.get(1).unwrap().as_str().replace('_', "");
if let Some((whole, decimal)) = number.split_once('.') {
if !whole.is_empty() {
let mut s = whole.to_string();
add_separators(&mut s, &SeparatorDir::Right, &self.number);
out.push_str(&s);
};
out.push('.');
if !decimal.is_empty() {
let mut s = decimal.to_string();
add_separators(&mut s, &SeparatorDir::Left, &self.number);
out.push_str(&s);
}
} else {
out.push_str(number.as_str());
add_separators(&mut out, &SeparatorDir::Right, &self.number);
}
}
if let Some(mark) = caps.get(2) {
out.push_str(mark.as_str());
}
if let Some(sign) = caps.get(3) {
out.push_str(sign.as_str());
}
if let Some(power) = caps.get(4) {
let mut s = power.as_str().replace('_', "");
add_separators(&mut s, &SeparatorDir::Right, &self.number);
out.push_str(&s);
}
out
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
struct NumericBaseConfig {
group_length: usize,
minimum_digits: usize,
}
impl NumericBaseConfig {
pub(self) fn set_numeric_base_from_config(&mut self, val: &serde_json::Value) {
if let Some(group_length) = val.get("groupLength").and_then(serde_json::Value::as_u64) {
self.group_length = usize::try_from(group_length).unwrap();
}
if let Some(minimum_digits) = val.get("minimumDigits").and_then(serde_json::Value::as_u64) {
self.minimum_digits = usize::try_from(minimum_digits).unwrap();
}
}
}
enum SeparatorDir {
Left,
Right,
}
fn add_separators(s: &mut String, dir: &SeparatorDir, config: &NumericBaseConfig) {
if s.len() < config.minimum_digits || s.len() < config.group_length + 1 {
return;
}
match dir {
SeparatorDir::Right => {
let mut pos = s.len();
while pos > config.group_length {
pos -= config.group_length;
s.insert(pos, '_');
}
}
SeparatorDir::Left => {
let mut pos = config.group_length;
while pos < s.len() {
s.insert(pos, '_');
pos += config.group_length + 1;
}
}
}
}
#[test]
fn test_with_snapshot() {
use crate::tester::Tester;
let fail = vec![
"const foo = 0b10_10_0001",
"const foo = 0b0_00_0",
"const foo = 0b10101010101010",
"const foo = 0B10101010101010",
"const foo = 0xA_B_CDE_F0",
"const foo = 0xABCDEF",
"const foo = 0xA_B",
"const foo = 0XAB_C_D",
"const foo = 0o12_34_5670",
"const foo = 0o7_7_77",
"const foo = 0o010101010101",
"const foo = 0O010101010101",
"const foo = 0b10_10_0001n",
"const foo = 0b0_00_0n",
"const foo = 0b10101010101010n",
"const foo = 0B10101010101010n",
"const foo = 1_9_223n",
"const foo = 80_7n",
"const foo = 123456789_100n",
"const foo = 1e10000",
"const foo = 39804e10000",
"const foo = -123456e100",
"const foo = -100000e-10000",
"const foo = -1000e+10000",
"const foo = -1000e+00010000",
"const foo = 3.6e12000",
"const foo = -1200000e5",
"const foo = 3.65432E12000",
"const foo = 9807.1234567",
"const foo = 3819.123_4325",
"const foo = 138789.12343_2_42",
"const foo = .000000_1",
"const foo = 12345678..toString()",
"const foo = 12345678 .toString()",
"const foo = .00000",
"const foo = 0.00000",
// Numbers
"const foo = 1_2_345_678",
"const foo = 12_3",
"const foo = 1234567890",
// Negative numbers
"const foo = -100000_1",
];
Tester::new_without_config(NumericSeparatorsStyle::NAME, vec![], fail).test_and_snapshot();
}
#[test]
fn test_number_binary() {
use crate::tester::Tester;
let pass = vec![
"const foo = 0b1010_0001_1000_0101",
"const foo = 0b0000",
"const foo = 0b10",
"const foo = 0b1_0111_0101_0101",
"const foo = 0B1010",
];
let fail = vec![
"const foo = 0b10_10_0001",
"const foo = 0b0_00_0",
"const foo = 0b10101010101010",
"const foo = 0B10101010101010",
];
let fix = vec![
("const foo = 0b10_10_0001", "const foo = 0b1010_0001", None),
("const foo = 0b0_00_0", "const foo = 0b0000", None),
("const foo = 0b10101010101010", "const foo = 0b10_1010_1010_1010", None),
("const foo = 0B10101010101010", "const foo = 0B10_1010_1010_1010", None),
];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_number_hexadecimal() {
use crate::tester::Tester;
let pass = vec![
"const foo = 0xAB_CD",
"const foo = 0xAB",
"const foo = 0xA",
"const foo = 0xA_BC_DE_F0",
"const foo = 0xab_e8_12",
"const foo = 0xe",
"const foo = 0Xab_e3_cd",
];
let fail = vec![
"const foo = 0xA_B_CDE_F0",
"const foo = 0xABCDEF",
"const foo = 0xA_B",
"const foo = 0XAB_C_D",
];
let fix = vec![("const foo = 0xA_B_CDE_F0", "const foo = 0xA_BC_DE_F0", None)];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_number_octal() {
use crate::tester::Tester;
let pass = vec![
"const foo = 0o1234_5670",
"const foo = 0o7777",
"const foo = 0o01",
"const foo = 0o12_7000_0000",
"const foo = 0O1111_1111",
// Legacy
"const foo = 0777777",
"let foo = 0111222",
];
let fail = vec![
"const foo = 0o12_34_5670",
"const foo = 0o7_7_77",
"const foo = 0o010101010101",
"const foo = 0O010101010101",
];
let fix = vec![("const foo = 0o12_34_5670", "const foo = 0o1234_5670", None)];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_bigint_binary() {
use crate::tester::Tester;
let pass = vec![
"const foo = 0b1010_0001_1000_0101n",
"const foo = 0b0000n",
"const foo = 0b10n",
"const foo = 0b1_0111_0101_0101n",
"const foo = 0B1010n",
];
let fail = vec![
"const foo = 0b10_10_0001n",
"const foo = 0b0_00_0n",
"const foo = 0b10101010101010n",
"const foo = 0B10101010101010n",
];
let fix = vec![
("const foo = 0b10_10_0001n", "const foo = 0b1010_0001n", None),
("const foo = 0b0_00_0n", "const foo = 0b0000n", None),
("const foo = 0b10101010101010n", "const foo = 0b10_1010_1010_1010n", None),
("const foo = 0B10101010101010n", "const foo = 0B10_1010_1010_1010n", None),
];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_bigint() {
use crate::tester::Tester;
let pass = vec![
"const foo = 9_223_372_036_854_775_807n",
"const foo = 807n",
"const foo = 1n",
"const foo = 9_372_854_807n",
"const foo = 9807n",
"const foo = 0n",
];
let fail = vec![
// BigInt
"const foo = 1_9_223n",
"const foo = 80_7n",
"const foo = 123456789_100n",
];
let fix = vec![("const foo = 1_9_223n", "const foo = 19_223n", None)];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_number_decimal_exponential() {
use crate::tester::Tester;
let pass = vec![
"const foo = 1e10_000",
"const foo = 39_804e1000",
"const foo = -123_456e-100",
"const foo = -100_000e-100_000",
"const foo = -100_000e+100_000",
"const foo = 3.6e12_000",
"const foo = 3.6E12_000",
"const foo = -1_200_000e5",
];
let fail = vec![
"const foo = 1e10000",
"const foo = 39804e10000",
"const foo = -123456e100",
"const foo = -100000e-10000",
"const foo = -1000e+10000",
"const foo = -1000e+00010000",
"const foo = 3.6e12000",
"const foo = -1200000e5",
"const foo = 3.65432E12000",
];
let fix = vec![
("const foo = 1e10000", "const foo = 1e10_000", None),
("const foo = 39804e10000", "const foo = 39_804e10_000", None),
("const foo = -123456e100", "const foo = -123_456e100", None),
("const foo = -100000e-10000", "const foo = -100_000e-10_000", None),
("const foo = -1000e+10000", "const foo = -1000e+10_000", None),
("const foo = -1000e+00010000", "const foo = -1000e+00_010_000", None),
("const foo = 3.6e12000", "const foo = 3.6e12_000", None),
("const foo = -1200000e5", "const foo = -1_200_000e5", None),
("const foo = 3.65432E12000", "const foo = 3.654_32E12_000", None),
];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_number_decimal_float() {
use crate::tester::Tester;
let pass = vec![
"const foo = 9807.123",
"const foo = 3819.123_432",
"const foo = 138_789.123_432_42",
"const foo = .000_000_1",
];
let fail = vec![
"const foo = 9807.1234567",
"const foo = 3819.123_4325",
"const foo = 138789.12343_2_42",
"const foo = .000000_1",
"const foo = 12345678..toString()",
"const foo = 12345678 .toString()",
"const foo = .00000",
"const foo = 0.00000",
];
let fix = vec![("const foo = 9807.1234567", "const foo = 9807.123_456_7", None)];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_number_decimal_integer() {
use crate::tester::Tester;
let pass = vec![
// Numbers
"const foo = 123_456",
"const foo = 12_345_678",
"const foo = 123",
"const foo = 1",
"const foo = 1234",
// Negative numbers
"const foo = -4000",
"const foo = -50_000",
"const foo = -600_000",
"const foo = -7_000_000",
"const foo = -80_000_000",
];
let fail = vec![
// Numbers
"const foo = 1_2_345_678",
"const foo = 12_3",
"const foo = 1234567890",
// Negative numbers
"const foo = -100000_1",
];
let fix = vec![
("const foo = 1234567890", "const foo = 1_234_567_890", None),
("const foo = -100000_1", "const foo = -1_000_001", None),
];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).expect_fix(fix).test();
}
#[test]
fn test_with_config() {
use crate::tester::Tester;
use serde_json::json;
let pass = vec![
("1234567890", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0b11111111", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0o77777777", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0xffffffff", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("1234567890n", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0b11111111n", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0o77777777n", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("0xffffffffn", Some(json!([{ "onlyIfContainsSeparator": true }]))),
("12_34_56", Some(json!([{ "number": { "groupLength": 2 } }]))),
("12345", Some(json!([{ "number": { "minimumDigits": 10 } }]))),
("0b1_1_1_1_1", Some(json!([{ "binary": { "groupLength": 1 } }]))),
("0o7_7_7_7_7", Some(json!([{ "octal": { "groupLength": 1 } }]))),
("0xf_f_f_f_f", Some(json!([{ "hexadecimal": { "groupLength": 1 } }]))),
("12_34_56n", Some(json!([{ "number": { "groupLength": 2 } }]))),
("12345n", Some(json!([{ "number": { "minimumDigits": 10 } }]))),
("0b1_1_1_1_1n", Some(json!([{ "binary": { "groupLength": 1 } }]))),
("0o7_7_7_7_7n", Some(json!([{ "octal": { "groupLength": 1 } }]))),
("0xf_f_f_f_fn", Some(json!([{ "hexadecimal": { "groupLength": 1 } }]))),
];
let fail = vec![];
Tester::new(NumericSeparatorsStyle::NAME, pass, fail).test();
}
#[test]
fn test_misc() {
use crate::tester::Tester;
let pass = vec![
"const foo = -282_932 - (1938 / 10_000) * .1 + 18.100_000_2",
"const foo = NaN",
"const foo = Infinity",
"const foo = -Infinity",
"const foo = '1234567n'",
];
let fail = vec![];
Tester::new_without_config(NumericSeparatorsStyle::NAME, pass, fail).test();
}
#[cfg(test)]
mod internal_tests {
use serde_json::json;
use super::*;
#[test]
fn test_from_configuration() {
let config = json!([{
"binary": {"groupLength": 2, "minimumDigits": 4},
"hexadecimal": {"groupLength": 8, "minimumDigits": 16},
"number": {"groupLength": 32, "minimumDigits": 64},
"octal": {"groupLength": 128, "minimumDigits": 256},
"onlyIfContainsSeparator": true
}]);
let rule = NumericSeparatorsStyle::from_configuration(config);
assert_eq!(rule.binary.group_length, 2);
assert_eq!(rule.binary.minimum_digits, 4);
assert_eq!(rule.hexadecimal.group_length, 8);
assert_eq!(rule.hexadecimal.minimum_digits, 16);
assert_eq!(rule.number.group_length, 32);
assert_eq!(rule.number.minimum_digits, 64);
assert_eq!(rule.octal.group_length, 128);
assert_eq!(rule.octal.minimum_digits, 256);
assert!(rule.only_if_contains_separator);
}
#[test]
fn test_from_empty_configuration() {
let rule = NumericSeparatorsStyle::from_configuration(json!([]));
assert_eq!(rule, NumericSeparatorsStyle::default());
}
}

View file

@ -0,0 +1,285 @@
---
source: crates/oxc_linter/src/tester.rs
expression: numeric_separators_style
---
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b10_10_0001
· ────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b0_00_0
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b10101010101010
· ────────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0B10101010101010
· ────────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0xA_B_CDE_F0
· ────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0xABCDEF
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0xA_B
· ─────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0XAB_C_D
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0o12_34_5670
· ────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0o7_7_77
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0o010101010101
· ──────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0O010101010101
· ──────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b10_10_0001n
· ─────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b0_00_0n
· ─────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0b10101010101010n
· ─────────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0B10101010101010n
· ─────────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 1_9_223n
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 80_7n
· ─────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 123456789_100n
· ──────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 1e10000
· ───────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 39804e10000
· ───────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -123456e100
· ──────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -100000e-10000
· ─────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -1000e+10000
· ───────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -1000e+00010000
· ──────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 3.6e12000
· ─────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -1200000e5
· ─────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 3.65432E12000
· ─────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 9807.1234567
· ────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 3819.123_4325
· ─────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 138789.12343_2_42
· ─────────────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = .000000_1
· ─────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 12345678..toString()
· ─────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 12345678 .toString()
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = .00000
· ──────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 0.00000
· ───────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 1_2_345_678
· ───────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 12_3
· ────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = 1234567890
· ──────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.
⚠ eslint-plugin-unicorn(numeric-separators-style): Invalid group length in numeric value.
╭─[numeric_separators_style.tsx:1:1]
1 │ const foo = -100000_1
· ────────
╰────
help: Group digits with numeric separators (_) so longer numbers are easier to read.