From 0b6749f827a5051f16a6b919504bbfab41011f13 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Sat, 5 Dec 2020 13:35:39 +0100 Subject: [PATCH 01/15] `numeric-separators-style`: Add `checkOnlyIfSeparator` option --- docs/rules/numeric-separators-style.md | 17 ++++++++++++++++ rules/numeric-separators-style.js | 27 +++++++++++++++----------- test/numeric-separators-style.js | 12 ++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index 843f75d8d9..429c700e54 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -33,6 +33,19 @@ If you want a custom group size for a specific number type, you can specify it h There are four number types; [`hexadecimal`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Hexadecimal), [`binary`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Binary), [`octal`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Octal) and [`number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type). Each of them can be associated with an object containing the following options: +**`checkOnlyIfSeparator`** + +Type: `boolean` + +Check only if the group sizes are valid **only** if there are groups, separated with an `_`. + +Example: +```js +const foo = 100000; // Pass, because there are no groups, so no check was performed. +const bar = 1_000_000; // Pass, because the group sizes are correct. +const baz = 10_0_000_0; // Fail, because there are groups, but they are incorrect. +``` + **`minimumDigits`** Type: `number` @@ -96,18 +109,22 @@ const foo = 0o12_7777; ```js { hexadecimal: { + checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 2 }, binary: { + checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4 }, octal: { + checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4 }, number: { + checkOnlyIfSeparator: false, minimumDigits: 5, groupLength: 3 } diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index 5411820476..5cd2e7f7e8 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -47,12 +47,7 @@ function formatNumber(value, options) { return formatted; } -function format(value, options) { - const { - prefix = '', - data - } = value.match(/^(?0[box])?(?.*)$/i).groups; - +function format(value, {prefix, data}, options) { const formatOption = options[prefix.toLowerCase()]; if (prefix) { @@ -70,10 +65,10 @@ function format(value, options) { } const defaultOptions = { - hexadecimal: {minimumDigits: 0, groupLength: 2}, - binary: {minimumDigits: 0, groupLength: 4}, - octal: {minimumDigits: 0, groupLength: 4}, - number: {minimumDigits: 5, groupLength: 3} + hexadecimal: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 2}, + binary: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4}, + octal: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4}, + number: {checkOnlyIfSeparator: false, minimumDigits: 5, groupLength: 3} }; const create = context => { const rawOptions = defaultsDeep({}, context.options[0], defaultOptions); @@ -101,7 +96,13 @@ const create = context => { return; } - const formatted = format(number.replace(/_/g, ''), options) + suffix; + const strippedNumber = number.replace(/_/g, ''); + const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; + if (options[prefix]?.checkOnlyIfSeparator && !raw.includes('_')) { + return; + } + + const formatted = format(strippedNumber, {prefix, data}, options) + suffix; if (raw !== formatted) { context.report({ @@ -117,6 +118,10 @@ const create = context => { const formatOptionsSchema = ({minimumDigits, groupLength}) => ({ type: 'object', properties: { + checkOnlyIfSeparator: { + type: 'boolean', + default: false + }, minimumDigits: { type: 'integer', minimum: 0, diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index 440291a1fc..bb8b059951 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -104,6 +104,18 @@ test({ { code: 'const foo = 0b111', options: [{number: {minimumDigits: 3, groupLength: 1}}] + }, + { + code: 'const foo = 12345', + options: [{number: {checkOnlyIfSeparator: true}}] + }, + { + code: 'const foo = 12_345', + options: [{number: {checkOnlyIfSeparator: true}}] + }, + { + code: 'const foo = 0xA_B_C_D_E', + options: [{hexadecimal: {checkOnlyIfSeparator: true, groupLength: 1}}] } ], invalid: [ From 4f2e37bf7438a1b0cb9699d35bc51e2065763aab Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Sat, 5 Dec 2020 13:46:29 +0100 Subject: [PATCH 02/15] Fix wording in the documentation --- docs/rules/numeric-separators-style.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index 429c700e54..bab35fe4b1 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -37,7 +37,7 @@ There are four number types; [`hexadecimal`](https://developer.mozilla.org/en-US Type: `boolean` -Check only if the group sizes are valid **only** if there are groups, separated with an `_`. +Check if the group sizes are valid **only** if there are groups separated with an `_`. Example: ```js From 6656f1fda929390965b616036c8ab2c9a50536e5 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Sat, 5 Dec 2020 13:52:59 +0100 Subject: [PATCH 03/15] Remove the use of optional chaining (for Node <= 12 --- rules/numeric-separators-style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index 5cd2e7f7e8..47862088f6 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -98,7 +98,7 @@ const create = context => { const strippedNumber = number.replace(/_/g, ''); const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; - if (options[prefix]?.checkOnlyIfSeparator && !raw.includes('_')) { + if (options[prefix.toLowerCase()].checkOnlyIfSeparator && !raw.includes('_')) { return; } From a6aa1ec340c0486337afbde033ead087194f9c38 Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 11 Jan 2021 13:14:33 +0100 Subject: [PATCH 04/15] Fix linebreak Co-authored-by: Sindre Sorhus --- docs/rules/numeric-separators-style.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index bab35fe4b1..0993b5e236 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -35,7 +35,8 @@ There are four number types; [`hexadecimal`](https://developer.mozilla.org/en-US **`checkOnlyIfSeparator`** -Type: `boolean` +Type: `boolean`\ +Default: `false` Check if the group sizes are valid **only** if there are groups separated with an `_`. From e5d756ce76d320426821b7fdb352b9ac29056b30 Mon Sep 17 00:00:00 2001 From: Elliot Date: Mon, 11 Jan 2021 13:14:50 +0100 Subject: [PATCH 05/15] Add extra line Co-authored-by: Sindre Sorhus --- docs/rules/numeric-separators-style.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index 0993b5e236..d01591abac 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -41,6 +41,7 @@ Default: `false` Check if the group sizes are valid **only** if there are groups separated with an `_`. Example: + ```js const foo = 100000; // Pass, because there are no groups, so no check was performed. const bar = 1_000_000; // Pass, because the group sizes are correct. From ceb92c4c3c4bb2b0f5d808edef1d28f3de8746d8 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 14:16:18 +0100 Subject: [PATCH 06/15] Add more tests --- test/numeric-separators-style.js | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index bb8b059951..9eed00fb5d 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -109,13 +109,53 @@ test({ code: 'const foo = 12345', options: [{number: {checkOnlyIfSeparator: true}}] }, + { + code: 'const foo = 12345678', + options: [{number: {checkOnlyIfSeparator: true}}] + }, { code: 'const foo = 12_345', options: [{number: {checkOnlyIfSeparator: true}}] }, + { + code: 'const foo = 1789.123_432_42', + options: [{number: {checkOnlyIfSeparator: true}}] + }, + { + code: 'const foo = -100_000e+100_000', + options: [{number: {checkOnlyIfSeparator: true}}] + }, + { + code: 'const foo = -100000e+100000', + options: [{number: {checkOnlyIfSeparator: true}}] + }, + { + code: 'const foo = -282_932 - (1938 / 10_000) * .1 + 18.100_000_2', + options: [{number: {checkOnlyIfSeparator: true}}] + }, { code: 'const foo = 0xA_B_C_D_E', options: [{hexadecimal: {checkOnlyIfSeparator: true, groupLength: 1}}] + }, + { + code: 'const foo = 0o7777', + options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 4}}] + }, + { + code: 'const foo = 0xABCDEF012', + options: [{hexadecimal: {checkOnlyIfSeparator: true}}] + },, + { + code: 'const foo = 0o777777', + options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 3}}] + }, + { + code: 'const foo = 0o777777', + options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 3, groupLength: 2}}] + }, + { + code: 'const foo = 0o777_777', + options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 2, groupLength: 3}}] } ], invalid: [ @@ -339,6 +379,12 @@ test({ options: [{number: {minimumDigits: 3, groupLength: 2}}], errors: [error], output: 'const foo = 0b111' + }, + { + code: 'const foo = -100000e+100000', + options: [{number: {checkOnlyIfSeparator: false}}], + errors: [error], + output: 'const foo = -100_000e+100_000' } ] }); From b83efd6668a4e59bff0836350d8738fe54156ce0 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 14:18:33 +0100 Subject: [PATCH 07/15] fix extra comma --- test/numeric-separators-style.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index 9eed00fb5d..b0bfee4a8f 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -144,7 +144,7 @@ test({ { code: 'const foo = 0xABCDEF012', options: [{hexadecimal: {checkOnlyIfSeparator: true}}] - },, + }, { code: 'const foo = 0o777777', options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 3}}] From a36fbd0a56facd2c689f7e225d1b20f3f729e2a4 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 17:53:21 +0100 Subject: [PATCH 08/15] checkOnlyIfSeparator -> onlyIfContainsSeparator --- docs/rules/numeric-separators-style.md | 10 ++++----- rules/numeric-separators-style.js | 12 +++++------ test/numeric-separators-style.js | 28 +++++++++++++------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index d01591abac..e1a23beee6 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -33,7 +33,7 @@ If you want a custom group size for a specific number type, you can specify it h There are four number types; [`hexadecimal`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Hexadecimal), [`binary`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Binary), [`octal`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#Octal) and [`number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type). Each of them can be associated with an object containing the following options: -**`checkOnlyIfSeparator`** +**`onlyIfContainsSeparator`** Type: `boolean`\ Default: `false` @@ -111,22 +111,22 @@ const foo = 0o12_7777; ```js { hexadecimal: { - checkOnlyIfSeparator: false, + onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 2 }, binary: { - checkOnlyIfSeparator: false, + onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4 }, octal: { - checkOnlyIfSeparator: false, + onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4 }, number: { - checkOnlyIfSeparator: false, + onlyIfContainsSeparator: false, minimumDigits: 5, groupLength: 3 } diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index 47862088f6..d6d2fc2d4d 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -65,10 +65,10 @@ function format(value, {prefix, data}, options) { } const defaultOptions = { - hexadecimal: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 2}, - binary: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4}, - octal: {checkOnlyIfSeparator: false, minimumDigits: 0, groupLength: 4}, - number: {checkOnlyIfSeparator: false, minimumDigits: 5, groupLength: 3} + hexadecimal: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 2}, + binary: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4}, + octal: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4}, + number: {onlyIfContainsSeparator: false, minimumDigits: 5, groupLength: 3} }; const create = context => { const rawOptions = defaultsDeep({}, context.options[0], defaultOptions); @@ -98,7 +98,7 @@ const create = context => { const strippedNumber = number.replace(/_/g, ''); const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; - if (options[prefix.toLowerCase()].checkOnlyIfSeparator && !raw.includes('_')) { + if (options[prefix.toLowerCase()].onlyIfContainsSeparator && !raw.includes('_')) { return; } @@ -118,7 +118,7 @@ const create = context => { const formatOptionsSchema = ({minimumDigits, groupLength}) => ({ type: 'object', properties: { - checkOnlyIfSeparator: { + onlyIfContainsSeparator: { type: 'boolean', default: false }, diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index b0bfee4a8f..6b51b1dbc1 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -107,55 +107,55 @@ test({ }, { code: 'const foo = 12345', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = 12345678', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = 12_345', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = 1789.123_432_42', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = -100_000e+100_000', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = -100000e+100000', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = -282_932 - (1938 / 10_000) * .1 + 18.100_000_2', - options: [{number: {checkOnlyIfSeparator: true}}] + options: [{number: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = 0xA_B_C_D_E', - options: [{hexadecimal: {checkOnlyIfSeparator: true, groupLength: 1}}] + options: [{hexadecimal: {onlyIfContainsSeparator: true, groupLength: 1}}] }, { code: 'const foo = 0o7777', - options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 4}}] + options: [{octal: {onlyIfContainsSeparator: true, minimumDigits: 4}}] }, { code: 'const foo = 0xABCDEF012', - options: [{hexadecimal: {checkOnlyIfSeparator: true}}] + options: [{hexadecimal: {onlyIfContainsSeparator: true}}] }, { code: 'const foo = 0o777777', - options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 3}}] + options: [{octal: {onlyIfContainsSeparator: true, minimumDigits: 3}}] }, { code: 'const foo = 0o777777', - options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 3, groupLength: 2}}] + options: [{octal: {onlyIfContainsSeparator: true, minimumDigits: 3, groupLength: 2}}] }, { code: 'const foo = 0o777_777', - options: [{octal: {checkOnlyIfSeparator: true, minimumDigits: 2, groupLength: 3}}] + options: [{octal: {onlyIfContainsSeparator: true, minimumDigits: 2, groupLength: 3}}] } ], invalid: [ @@ -382,7 +382,7 @@ test({ }, { code: 'const foo = -100000e+100000', - options: [{number: {checkOnlyIfSeparator: false}}], + options: [{number: {onlyIfContainsSeparator: false}}], errors: [error], output: 'const foo = -100_000e+100_000' } From c8d4581113b38b498303b4e73a71fb0b6c2f3b8a Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 18:05:34 +0100 Subject: [PATCH 09/15] Add toplevel onlyIfContainsSeparator --- rules/numeric-separators-style.js | 20 ++++++++++++++++---- test/numeric-separators-style.js | 16 ++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index d6d2fc2d4d..cb3ba234f0 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -73,6 +73,7 @@ const defaultOptions = { const create = context => { const rawOptions = defaultsDeep({}, context.options[0], defaultOptions); const options = { + onlyIfContainsSeparator: rawOptions.onlyIfContainsSeparator, '0b': rawOptions.binary, '0o': rawOptions.octal, '0x': rawOptions.hexadecimal, @@ -98,7 +99,11 @@ const create = context => { const strippedNumber = number.replace(/_/g, ''); const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; - if (options[prefix.toLowerCase()].onlyIfContainsSeparator && !raw.includes('_')) { + + const { onlyIfContainsSeparator } = typeof options.onlyIfContainsSeparator === 'undefined' ? + options[prefix.toLowerCase()] : + options; + if (onlyIfContainsSeparator && !raw.includes('_')) { return; } @@ -138,9 +143,16 @@ const formatOptionsSchema = ({minimumDigits, groupLength}) => ({ const schema = [{ type: 'object', - properties: fromPairs( - Object.entries(defaultOptions).map(([type, options]) => [type, formatOptionsSchema(options)]) - ), + properties: { + ...fromPairs( + Object.entries(defaultOptions).map(([type, options]) => [type, formatOptionsSchema(options)]) + ), + onlyIfContainsSeparator: { + type: 'boolean', + // Default to undefined to avoid overriding properties' settings + default: undefined, + } + }, additionalProperties: false }]; diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index 6b51b1dbc1..3198a1b126 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -156,6 +156,22 @@ test({ { code: 'const foo = 0o777_777', options: [{octal: {onlyIfContainsSeparator: true, minimumDigits: 2, groupLength: 3}}] + }, + { + code: 'const foo = 0b01010101', + options: [{onlyIfContainsSeparator: true, binary: {onlyIfContainsSeparator: true}}] + }, + { + code: 'const foo = 0b01010101', + options: [{onlyIfContainsSeparator: true, binary: {onlyIfContainsSeparator: false}}] + }, + { + code: 'const foo = 0b0101_0101', + options: [{onlyIfContainsSeparator: false, binary: {onlyIfContainsSeparator: true}}] + }, + { + code: 'const foo = 0b0101_0101', + options: [{onlyIfContainsSeparator: false, binary: {onlyIfContainsSeparator: false}}] } ], invalid: [ From 977852604d68ecaa24b0cd397efc22888f12a558 Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 18:07:20 +0100 Subject: [PATCH 10/15] lint --- rules/numeric-separators-style.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index cb3ba234f0..0986cf8ce0 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -100,7 +100,7 @@ const create = context => { const strippedNumber = number.replace(/_/g, ''); const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; - const { onlyIfContainsSeparator } = typeof options.onlyIfContainsSeparator === 'undefined' ? + const {onlyIfContainsSeparator} = typeof options.onlyIfContainsSeparator === 'undefined' ? options[prefix.toLowerCase()] : options; if (onlyIfContainsSeparator && !raw.includes('_')) { @@ -150,7 +150,7 @@ const schema = [{ onlyIfContainsSeparator: { type: 'boolean', // Default to undefined to avoid overriding properties' settings - default: undefined, + default: undefined } }, additionalProperties: false From d719865bc6c794e97735b0ad6806a02154edc1ba Mon Sep 17 00:00:00 2001 From: Elliot Maisl Date: Mon, 18 Jan 2021 18:36:12 +0100 Subject: [PATCH 11/15] Add top-level onlyIfContainsSeparator to docs --- docs/rules/numeric-separators-style.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index e1a23beee6..808ea86b57 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -39,6 +39,7 @@ Type: `boolean`\ Default: `false` Check if the group sizes are valid **only** if there are groups separated with an `_`. +You can set it for each specific number type, or set the top-level one which will override others. Example: @@ -110,6 +111,7 @@ const foo = 0o12_7777; ```js { + onlyIfContainsSeparator: undefined, hexadecimal: { onlyIfContainsSeparator: false, minimumDigits: 0, From ebf5aeee6f8e3054e0a0bd6681bdb76c853a8afd Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 19 Jan 2021 10:02:40 +0800 Subject: [PATCH 12/15] Correct logic --- docs/rules/numeric-separators-style.md | 9 ++-- rules/numeric-separators-style.js | 57 ++++++++++++++++++-------- test/numeric-separators-style.js | 4 -- 3 files changed, 44 insertions(+), 26 deletions(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index 808ea86b57..e33bf937b0 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -39,14 +39,15 @@ Type: `boolean`\ Default: `false` Check if the group sizes are valid **only** if there are groups separated with an `_`. -You can set it for each specific number type, or set the top-level one which will override others. +You can set it at top-level, or override for each specific number type. Example: ```js -const foo = 100000; // Pass, because there are no groups, so no check was performed. -const bar = 1_000_000; // Pass, because the group sizes are correct. -const baz = 10_0_000_0; // Fail, because there are groups, but they are incorrect. +// eslint unicorn/numeric-separators-style: ["error", {"onlyIfContainsSeparator": true, {"binary": "onlyIfContainsSeparator": false}] +const number = 100000; // Pass, this number does not contains separators +const binary = 0b101010001; // Fail, `binary` type don't require separators +const hexadecimal = 0xD_EED_BEE_F; // Fail, it contain separators, and it's incorrectly grouped ``` **`minimumDigits`** diff --git a/rules/numeric-separators-style.js b/rules/numeric-separators-style.js index 0986cf8ce0..5810e99ae5 100644 --- a/rules/numeric-separators-style.js +++ b/rules/numeric-separators-style.js @@ -1,5 +1,5 @@ 'use strict'; -const {defaultsDeep, fromPairs} = require('lodash'); +const {fromPairs} = require('lodash'); const getDocumentationUrl = require('./utils/get-documentation-url'); const MESSAGE_ID = 'numeric-separators-style'; @@ -65,19 +65,44 @@ function format(value, {prefix, data}, options) { } const defaultOptions = { - hexadecimal: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 2}, - binary: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4}, - octal: {onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4}, - number: {onlyIfContainsSeparator: false, minimumDigits: 5, groupLength: 3} + binary: {minimumDigits: 0, groupLength: 4}, + octal: {minimumDigits: 0, groupLength: 4}, + hexadecimal: {minimumDigits: 0, groupLength: 2}, + number: {minimumDigits: 5, groupLength: 3} }; const create = context => { - const rawOptions = defaultsDeep({}, context.options[0], defaultOptions); + const { + onlyIfContainsSeparator, + binary, + octal, + hexadecimal, + number + } = { + onlyIfContainsSeparator: false, + ...context.options[0] + }; + const options = { - onlyIfContainsSeparator: rawOptions.onlyIfContainsSeparator, - '0b': rawOptions.binary, - '0o': rawOptions.octal, - '0x': rawOptions.hexadecimal, - '': rawOptions.number + '0b': { + onlyIfContainsSeparator, + ...defaultOptions.binary, + ...binary + }, + '0o': { + onlyIfContainsSeparator, + ...defaultOptions.octal, + ...octal + }, + '0x': { + onlyIfContainsSeparator, + ...defaultOptions.hexadecimal, + ...hexadecimal + }, + '': { + onlyIfContainsSeparator, + ...defaultOptions.number, + ...number + } }; return { @@ -100,9 +125,7 @@ const create = context => { const strippedNumber = number.replace(/_/g, ''); const {prefix = '', data} = strippedNumber.match(/^(?0[box])?(?.*)$/i).groups; - const {onlyIfContainsSeparator} = typeof options.onlyIfContainsSeparator === 'undefined' ? - options[prefix.toLowerCase()] : - options; + const {onlyIfContainsSeparator} = options[prefix.toLowerCase()]; if (onlyIfContainsSeparator && !raw.includes('_')) { return; } @@ -124,8 +147,7 @@ const formatOptionsSchema = ({minimumDigits, groupLength}) => ({ type: 'object', properties: { onlyIfContainsSeparator: { - type: 'boolean', - default: false + type: 'boolean' }, minimumDigits: { type: 'integer', @@ -149,8 +171,7 @@ const schema = [{ ), onlyIfContainsSeparator: { type: 'boolean', - // Default to undefined to avoid overriding properties' settings - default: undefined + default: false } }, additionalProperties: false diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index 3198a1b126..bbc764a7a9 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -161,10 +161,6 @@ test({ code: 'const foo = 0b01010101', options: [{onlyIfContainsSeparator: true, binary: {onlyIfContainsSeparator: true}}] }, - { - code: 'const foo = 0b01010101', - options: [{onlyIfContainsSeparator: true, binary: {onlyIfContainsSeparator: false}}] - }, { code: 'const foo = 0b0101_0101', options: [{onlyIfContainsSeparator: false, binary: {onlyIfContainsSeparator: true}}] From 08642da8d1c19137feb846c0f53371394c3c8329 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 19 Jan 2021 10:34:40 +0800 Subject: [PATCH 13/15] Add more tests --- test/numeric-separators-style.js | 135 +++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/test/numeric-separators-style.js b/test/numeric-separators-style.js index bbc764a7a9..ffce7c2d31 100644 --- a/test/numeric-separators-style.js +++ b/test/numeric-separators-style.js @@ -1,3 +1,4 @@ +import {outdent} from 'outdent'; import {test} from './utils/test'; const error = { @@ -105,6 +106,59 @@ test({ code: 'const foo = 0b111', options: [{number: {minimumDigits: 3, groupLength: 1}}] }, + { + code: outdent` + const binary = 0b10101010; + const octal = 0o76543210; + const hexadecimal = 0xfedcba97; + const number = 12345678.12345678e12345678; + `, + options: [{ + onlyIfContainsSeparator: true + }] + }, + { + code: outdent` + const binary = 0b1010_1010; + const octal = 0o76543210; + const hexadecimal = 0xfedcba97; + const number = 12345678.12345678e12345678; + `, + options: [{ + onlyIfContainsSeparator: true, + binary: { + onlyIfContainsSeparator: false + } + }] + }, + { + code: outdent` + const binary = 0b10_10_10_10; + const octal = 0o76543210; + const hexadecimal = 0xfedcba97; + const number = 12345678.12345678e12345678; + `, + options: [{ + onlyIfContainsSeparator: true, + binary: { + onlyIfContainsSeparator: false, + groupLength: 2 + } + }] + }, + { + code: outdent` + const binary = 0b10101010; + const octal = 0o7654_3210; + const hexadecimal = 0xfe_dc_ba_97; + const number = 12_345_678.123_456_78e12_345_678; + `, + options: [{ + binary: { + onlyIfContainsSeparator: true + } + }] + }, { code: 'const foo = 12345', options: [{number: {onlyIfContainsSeparator: true}}] @@ -397,6 +451,87 @@ test({ options: [{number: {onlyIfContainsSeparator: false}}], errors: [error], output: 'const foo = -100_000e+100_000' + }, + { + code: outdent` + const binary = 0b10_101010; + const octal = 0o76_543210; + const hexadecimal = 0xfe_dcba97; + const number = 12_345678.12345678e12345678; + `, + output: outdent` + const binary = 0b1010_1010; + const octal = 0o7654_3210; + const hexadecimal = 0xfe_dc_ba_97; + const number = 12_345_678.123_456_78e12_345_678; + `, + options: [{ + onlyIfContainsSeparator: true + }], + errors: 4 + }, + { + code: outdent` + const binary = 0b10101010; + const octal = 0o76_543210; + const hexadecimal = 0xfe_dcba97; + const number = 12_345678.12345678e12345678; + `, + output: outdent` + const binary = 0b1010_1010; + const octal = 0o7654_3210; + const hexadecimal = 0xfe_dc_ba_97; + const number = 12_345_678.123_456_78e12_345_678; + `, + options: [{ + onlyIfContainsSeparator: true, + binary: { + onlyIfContainsSeparator: false + } + }], + errors: 4 + }, + { + code: outdent` + const binary = 0b10101010; + const octal = 0o76_543210; + const hexadecimal = 0xfe_dcba97; + const number = 12_345678.12345678e12345678; + `, + output: outdent` + const binary = 0b10_10_10_10; + const octal = 0o7654_3210; + const hexadecimal = 0xfe_dc_ba_97; + const number = 12_345_678.123_456_78e12_345_678; + `, + options: [{ + onlyIfContainsSeparator: true, + binary: { + onlyIfContainsSeparator: false, + groupLength: 2 + } + }], + errors: 4 + }, + { + code: outdent` + const binary = 0b10_101010; + const octal = 0o76543210; + const hexadecimal = 0xfedcba97; + const number = 12345678.12345678e12345678; + `, + output: outdent` + const binary = 0b1010_1010; + const octal = 0o7654_3210; + const hexadecimal = 0xfe_dc_ba_97; + const number = 12_345_678.123_456_78e12_345_678; + `, + options: [{ + binary: { + onlyIfContainsSeparator: true + } + }], + errors: 4 } ] }); From ffa3e9e88c12bcb437da669120a28ce9127c861d Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 19 Jan 2021 10:37:10 +0800 Subject: [PATCH 14/15] Typo --- docs/rules/numeric-separators-style.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index e33bf937b0..846e0c6d3f 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -44,10 +44,10 @@ You can set it at top-level, or override for each specific number type. Example: ```js -// eslint unicorn/numeric-separators-style: ["error", {"onlyIfContainsSeparator": true, {"binary": "onlyIfContainsSeparator": false}] +// eslint unicorn/numeric-separators-style: ["error", {"onlyIfContainsSeparator": true, "binary": {"onlyIfContainsSeparator": false}] const number = 100000; // Pass, this number does not contains separators const binary = 0b101010001; // Fail, `binary` type don't require separators -const hexadecimal = 0xD_EED_BEE_F; // Fail, it contain separators, and it's incorrectly grouped +const hexadecimal = 0xD_EED_BEE_F; // Fail, it contain separators and it's incorrectly grouped ``` **`minimumDigits`** From ee2b52e5d4388be6a16f1707d729b3b8333d410e Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 19 Jan 2021 10:39:10 +0800 Subject: [PATCH 15/15] Update default value --- docs/rules/numeric-separators-style.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/rules/numeric-separators-style.md b/docs/rules/numeric-separators-style.md index 846e0c6d3f..a15986233e 100644 --- a/docs/rules/numeric-separators-style.md +++ b/docs/rules/numeric-separators-style.md @@ -112,24 +112,20 @@ const foo = 0o12_7777; ```js { - onlyIfContainsSeparator: undefined, + onlyIfContainsSeparator: false, hexadecimal: { - onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 2 }, binary: { - onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4 }, octal: { - onlyIfContainsSeparator: false, minimumDigits: 0, groupLength: 4 }, number: { - onlyIfContainsSeparator: false, minimumDigits: 5, groupLength: 3 }