From c5b36afc6cb83e1d694bc70b932582c5b3894727 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Tue, 3 Dec 2019 10:45:53 +0100 Subject: [PATCH 01/12] Allow disabling of regexp character sorting Fixes #453 Improved by https://github.com/DmitrySoshnikov/regexp-tree/pull/200 --- docs/rules/regex-shorthand.md | 9 +++++++ rules/regex-shorthand.js | 44 +++++++++++++++++++++++++++++++++-- test/regex-shorthand.js | 18 +++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index a00d13abc4..770af25f44 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -27,3 +27,12 @@ const regex = /\W/; const regex = /\W/i; const regex = /\d\.\w\-\D/i; ``` + +## Options + +### disableCharacterSorting + +Type: `boolean`
+Default: `false` + +Disables optimizations that affects the sorting of characters. diff --git a/rules/regex-shorthand.js b/rules/regex-shorthand.js index 39f4455b82..fe871dc5d7 100644 --- a/rules/regex-shorthand.js +++ b/rules/regex-shorthand.js @@ -6,7 +6,36 @@ const quoteString = require('./utils/quote-string'); const message = 'Use regex shorthands to improve readability.'; +const availableRegexpTreeOptimizations = [ + 'charSurrogatePairToSingleUnicode', + 'charCodeToSimpleChar', + 'charCaseInsensitiveLowerCaseTransform', + 'charClassRemoveDuplicates', + 'quantifiersMerge', + 'quantifierRangeToSymbol', + 'charClassClassrangesToChars', + 'charClassClassrangesMerge', + 'charClassToMeta', + 'charClassToSingleChar', + 'charEscapeUnescape', + 'disjunctionRemoveDuplicates', + 'groupSingleCharsToCharClass', + 'removeEmptyGroup', + 'ungroup', + 'combineRepeatingPatterns' +]; + +const generateRegexpTreeWhitelistFromBlacklist = blacklist => availableRegexpTreeOptimizations.filter(optimization => !blacklist.includes(optimization)); + const create = context => { + const {disableCharacterSorting} = context.options[0] || {}; + + let whitelist; + + if (disableCharacterSorting) { + whitelist = generateRegexpTreeWhitelistFromBlacklist(['charClassClassrangesMerge']); + } + return { 'Literal[regex]': node => { const {raw: original, regex} = node; @@ -20,7 +49,7 @@ const create = context => { let optimized = original; try { - optimized = optimize(original).toString(); + optimized = optimize(original, whitelist).toString(); } catch (_) {} if (original === optimized) { @@ -69,6 +98,16 @@ const create = context => { }; }; +const schema = [{ + type: 'object', + properties: { + disableCharacterSorting: { + type: 'boolean', + default: false + } + } +}]; + module.exports = { create, meta: { @@ -76,6 +115,7 @@ module.exports = { docs: { url: getDocumentationUrl(__filename) }, - fixable: 'code' + fixable: 'code', + schema } }; diff --git a/test/regex-shorthand.js b/test/regex-shorthand.js index dcceeab680..1d83adc649 100644 --- a/test/regex-shorthand.js +++ b/test/regex-shorthand.js @@ -13,6 +13,10 @@ const error = { message: 'Use regex shorthands to improve readability.' }; +const disableCharacterSortingOptions = [{ + disableCharacterSorting: true +}]; + ruleTester.run('regex-shorthand', rule, { valid: [ 'const foo = /\\d/', @@ -36,7 +40,11 @@ ruleTester.run('regex-shorthand', rule, { // Should not suggest wrong regex (#447) '/(\\s|\\.|@|_|-)/u', - '/[\\s.@_-]/u' + '/[\\s.@_-]/u', + { + code: '/[åä]/', + options: disableCharacterSortingOptions + } ], invalid: [ { @@ -250,6 +258,14 @@ ruleTester.run('regex-shorthand', rule, { message: '/^by @([a-zA-Z0-9-]+)/ can be optimized to /^by @([\\d-A-Za-z]+)/' }], output: 'const foo = /^by @([\\d-A-Za-z]+)/' + }, + { + code: 'const foo = /[åä]/', + errors: [{ + ...error, + message: '/[åä]/ can be optimized to /[äå]/' + }], + output: 'const foo = /[äå]/' } ] }); From 9b2db0cb54a2d2cac66ed00490cf7793daa5a53b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 3 Dec 2019 17:00:12 +0700 Subject: [PATCH 02/12] Update regex-shorthand.md --- docs/rules/regex-shorthand.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index 770af25f44..7d7eeaf9a1 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -2,7 +2,6 @@ This rule is fixable. - ## Fail ```js @@ -15,7 +14,6 @@ const regex = /[^a-z0-9_]/i; const regex = /[0-9]\.[a-zA-Z0-9_]\-[^0-9]/i; ``` - ## Pass ```js @@ -32,7 +30,7 @@ const regex = /\d\.\w\-\D/i; ### disableCharacterSorting -Type: `boolean`
+Type: `boolean`\ Default: `false` Disables optimizations that affects the sorting of characters. From 99418991f501bbb5933c15aeeaa4d0ceff5d7040 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 3 Dec 2019 22:59:50 +0800 Subject: [PATCH 03/12] Add complicated case --- test/regex-shorthand.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/regex-shorthand.js b/test/regex-shorthand.js index 1d83adc649..85aeadda10 100644 --- a/test/regex-shorthand.js +++ b/test/regex-shorthand.js @@ -41,8 +41,9 @@ ruleTester.run('regex-shorthand', rule, { // Should not suggest wrong regex (#447) '/(\\s|\\.|@|_|-)/u', '/[\\s.@_-]/u', + { - code: '/[åä]/', + code: '/[GgHhIiå.Z:a-f"0-8%A*ä]/', options: disableCharacterSortingOptions } ], @@ -260,12 +261,12 @@ ruleTester.run('regex-shorthand', rule, { output: 'const foo = /^by @([\\d-A-Za-z]+)/' }, { - code: 'const foo = /[åä]/', + code: '/[GgHhIiå.Z:a-f"0-8%A*ä]/', errors: [{ ...error, - message: '/[åä]/ can be optimized to /[äå]/' + message: '/[GgHhIiå.Z:a-f"0-8%A*ä]/ can be optimized to /["%*.0-8:AG-IZa-iäå]/' }], - output: 'const foo = /[äå]/' + output: '/["%*.0-8:AG-IZa-iäå]/' } ] }); From 89342635e08b40952acc35b58187b916d7407f35 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Tue, 3 Dec 2019 16:03:15 +0100 Subject: [PATCH 04/12] Add TODO --- rules/regex-shorthand.js | 1 + 1 file changed, 1 insertion(+) diff --git a/rules/regex-shorthand.js b/rules/regex-shorthand.js index fe871dc5d7..f426ab87d2 100644 --- a/rules/regex-shorthand.js +++ b/rules/regex-shorthand.js @@ -6,6 +6,7 @@ const quoteString = require('./utils/quote-string'); const message = 'Use regex shorthands to improve readability.'; +// TODO: Simplify when/if this PR gets merged: https://github.com/DmitrySoshnikov/regexp-tree/pull/200 const availableRegexpTreeOptimizations = [ 'charSurrogatePairToSingleUnicode', 'charCodeToSimpleChar', From 7438f3a676ba90754facd1bc5b90760c901c570a Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Tue, 3 Dec 2019 18:35:21 +0100 Subject: [PATCH 05/12] Rename option --- docs/rules/regex-shorthand.md | 4 ++-- rules/regex-shorthand.js | 9 ++++----- test/regex-shorthand.js | 6 +++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index 7d7eeaf9a1..f264b6c57a 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -28,9 +28,9 @@ const regex = /\d\.\w\-\D/i; ## Options -### disableCharacterSorting +### sortCharacterClasses Type: `boolean`\ -Default: `false` +Default: `true` Disables optimizations that affects the sorting of characters. diff --git a/rules/regex-shorthand.js b/rules/regex-shorthand.js index f426ab87d2..8fddf25a3f 100644 --- a/rules/regex-shorthand.js +++ b/rules/regex-shorthand.js @@ -29,11 +29,11 @@ const availableRegexpTreeOptimizations = [ const generateRegexpTreeWhitelistFromBlacklist = blacklist => availableRegexpTreeOptimizations.filter(optimization => !blacklist.includes(optimization)); const create = context => { - const {disableCharacterSorting} = context.options[0] || {}; + const {sortCharacterClasses} = context.options[0] || {}; let whitelist; - if (disableCharacterSorting) { + if (sortCharacterClasses === false) { whitelist = generateRegexpTreeWhitelistFromBlacklist(['charClassClassrangesMerge']); } @@ -102,9 +102,8 @@ const create = context => { const schema = [{ type: 'object', properties: { - disableCharacterSorting: { - type: 'boolean', - default: false + sortCharacterClasses: { + type: 'boolean' } } }]; diff --git a/test/regex-shorthand.js b/test/regex-shorthand.js index 85aeadda10..ee55e6a079 100644 --- a/test/regex-shorthand.js +++ b/test/regex-shorthand.js @@ -13,8 +13,8 @@ const error = { message: 'Use regex shorthands to improve readability.' }; -const disableCharacterSortingOptions = [{ - disableCharacterSorting: true +const disableSortCharacterClassesOptions = [{ + sortCharacterClasses: false }]; ruleTester.run('regex-shorthand', rule, { @@ -44,7 +44,7 @@ ruleTester.run('regex-shorthand', rule, { { code: '/[GgHhIiå.Z:a-f"0-8%A*ä]/', - options: disableCharacterSortingOptions + options: disableSortCharacterClassesOptions } ], invalid: [ From fcd8038c9f05db0f2140de5872c26b3ad109e5eb Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 11 Dec 2019 11:37:48 +0800 Subject: [PATCH 06/12] Use `regexp-tree` blacklist --- rules/regex-shorthand.js | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/rules/regex-shorthand.js b/rules/regex-shorthand.js index 8fddf25a3f..d6007af23b 100644 --- a/rules/regex-shorthand.js +++ b/rules/regex-shorthand.js @@ -6,35 +6,13 @@ const quoteString = require('./utils/quote-string'); const message = 'Use regex shorthands to improve readability.'; -// TODO: Simplify when/if this PR gets merged: https://github.com/DmitrySoshnikov/regexp-tree/pull/200 -const availableRegexpTreeOptimizations = [ - 'charSurrogatePairToSingleUnicode', - 'charCodeToSimpleChar', - 'charCaseInsensitiveLowerCaseTransform', - 'charClassRemoveDuplicates', - 'quantifiersMerge', - 'quantifierRangeToSymbol', - 'charClassClassrangesToChars', - 'charClassClassrangesMerge', - 'charClassToMeta', - 'charClassToSingleChar', - 'charEscapeUnescape', - 'disjunctionRemoveDuplicates', - 'groupSingleCharsToCharClass', - 'removeEmptyGroup', - 'ungroup', - 'combineRepeatingPatterns' -]; - -const generateRegexpTreeWhitelistFromBlacklist = blacklist => availableRegexpTreeOptimizations.filter(optimization => !blacklist.includes(optimization)); - const create = context => { const {sortCharacterClasses} = context.options[0] || {}; - let whitelist; + const blacklist = []; if (sortCharacterClasses === false) { - whitelist = generateRegexpTreeWhitelistFromBlacklist(['charClassClassrangesMerge']); + blacklist.push('charClassClassrangesMerge'); } return { @@ -50,7 +28,7 @@ const create = context => { let optimized = original; try { - optimized = optimize(original, whitelist).toString(); + optimized = optimize(original, undefined, {blacklist}).toString(); } catch (_) {} if (original === optimized) { @@ -103,7 +81,8 @@ const schema = [{ type: 'object', properties: { sortCharacterClasses: { - type: 'boolean' + type: 'boolean', + default: true, } } }]; From a99036801b4656b3817eb624a22f5236f10f32b1 Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 11 Dec 2019 11:45:48 +0800 Subject: [PATCH 07/12] Fix style --- rules/regex-shorthand.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/regex-shorthand.js b/rules/regex-shorthand.js index d6007af23b..0c20a74bb0 100644 --- a/rules/regex-shorthand.js +++ b/rules/regex-shorthand.js @@ -82,7 +82,7 @@ const schema = [{ properties: { sortCharacterClasses: { type: 'boolean', - default: true, + default: true } } }]; From 8e5d513f62d1074aa451d326d124de9efcb3998b Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 11 Dec 2019 11:50:05 +0800 Subject: [PATCH 08/12] extra test --- test/regex-shorthand.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/test/regex-shorthand.js b/test/regex-shorthand.js index ee55e6a079..3fb6901e2a 100644 --- a/test/regex-shorthand.js +++ b/test/regex-shorthand.js @@ -267,6 +267,16 @@ ruleTester.run('regex-shorthand', rule, { message: '/[GgHhIiå.Z:a-f"0-8%A*ä]/ can be optimized to /["%*.0-8:AG-IZa-iäå]/' }], output: '/["%*.0-8:AG-IZa-iäå]/' - } + }, + // Should still use shorthand when disabling sort character classes + { + code: '/[a0-9b]/', + options: disableSortCharacterClassesOptions, + errors: [{ + ...error, + message: '/[a0-9b]/ can be optimized to /[a\\db]/' + }], + output: '/[a\\db]/' + }, ] }); From df48bd886bdeaef9297a8ebb1f25b5ca027ac2dd Mon Sep 17 00:00:00 2001 From: fisker Date: Wed, 11 Dec 2019 12:43:11 +0800 Subject: [PATCH 09/12] Fix style --- test/regex-shorthand.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/regex-shorthand.js b/test/regex-shorthand.js index 3fb6901e2a..c43a18a6f3 100644 --- a/test/regex-shorthand.js +++ b/test/regex-shorthand.js @@ -277,6 +277,6 @@ ruleTester.run('regex-shorthand', rule, { message: '/[a0-9b]/ can be optimized to /[a\\db]/' }], output: '/[a\\db]/' - }, + } ] }); From 36e737296f5d9c0620731c46c14e414a25c2e9f8 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Sun, 29 Dec 2019 23:06:52 +0100 Subject: [PATCH 10/12] Update docs/rules/regex-shorthand.md Co-Authored-By: Sindre Sorhus --- docs/rules/regex-shorthand.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index f264b6c57a..2338393176 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -33,4 +33,4 @@ const regex = /\d\.\w\-\D/i; Type: `boolean`\ Default: `true` -Disables optimizations that affects the sorting of characters. +Disables optimizations that affects the sorting of character classes. From 908c7dd79d28b4557f64beaf36086fba80f89b74 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Sat, 25 Jan 2020 16:37:27 +0100 Subject: [PATCH 11/12] Add example as requested by @sindresorhus --- docs/rules/regex-shorthand.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index 2338393176..3881b4b851 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -33,4 +33,4 @@ const regex = /\d\.\w\-\D/i; Type: `boolean`\ Default: `true` -Disables optimizations that affects the sorting of character classes. +Disables optimizations that affects the sorting of character classes. Eg. preserves `[AaQqTt]` in its order rather then resorting it to `[AQTaqt]` From 372d2850573320d9ff113ed1dad12818f0b5298b Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Sun, 26 Jan 2020 13:59:48 +0700 Subject: [PATCH 12/12] Update regex-shorthand.md --- docs/rules/regex-shorthand.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/regex-shorthand.md b/docs/rules/regex-shorthand.md index 3881b4b851..db42628bc5 100644 --- a/docs/rules/regex-shorthand.md +++ b/docs/rules/regex-shorthand.md @@ -33,4 +33,4 @@ const regex = /\d\.\w\-\D/i; Type: `boolean`\ Default: `true` -Disables optimizations that affects the sorting of character classes. Eg. preserves `[AaQqTt]` in its order rather then resorting it to `[AQTaqt]` +Disables optimizations that affect the sorting of character classes. For example, preserves the order of the characters in `[AaQqTt]` rather than sorting it to `[AQTaqt]`.