From b7fad2b52f23667628cf209663795a721c88d0ba Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Tue, 25 Jul 2023 18:44:36 +0900 Subject: [PATCH] feat: `prefer-regex-literals` support `v` flag (#17410) * feat: `prefer-regex-literals` support `v` flag * Update tests/lib/rules/prefer-regex-literals.js Co-authored-by: Milos Djermanovic --------- Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 12 +- lib/rules/utils/regular-expressions.js | 2 +- tests/lib/rules/prefer-regex-literals.js | 182 ++++++++++++++++++++++- 3 files changed, 191 insertions(+), 5 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index eca805483f4..ffaaeac3f27 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -241,7 +241,7 @@ module.exports = { /** * Returns a ecmaVersion compatible for regexpp. * @param {number} ecmaVersion The ecmaVersion to convert. - * @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp. + * @returns {import("@eslint-community/regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp. */ function getRegexppEcmaVersion(ecmaVersion) { if (ecmaVersion <= 5) { @@ -297,7 +297,10 @@ module.exports = { const validator = new RegExpValidator({ ecmaVersion: regexppEcmaVersion }); try { - validator.validatePattern(pattern, 0, pattern.length, flags ? flags.includes("u") : false); + validator.validatePattern(pattern, 0, pattern.length, { + unicode: flags ? flags.includes("u") : false, + unicodeSets: flags ? flags.includes("v") : false + }); if (flags) { validator.validateFlags(flags); } @@ -461,7 +464,10 @@ module.exports = { if (regexContent && !noFix) { let charIncrease = 0; - const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); + const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, { + unicode: flags ? flags.includes("u") : false, + unicodeSets: flags ? flags.includes("v") : false + }); visitRegExpAST(ast, { onCharacterEnter(characterNode) { diff --git a/lib/rules/utils/regular-expressions.js b/lib/rules/utils/regular-expressions.js index 234a1cb8b11..92da774c96c 100644 --- a/lib/rules/utils/regular-expressions.js +++ b/lib/rules/utils/regular-expressions.js @@ -8,7 +8,7 @@ const { RegExpValidator } = require("@eslint-community/regexpp"); -const REGEXPP_LATEST_ECMA_VERSION = 2022; +const REGEXPP_LATEST_ECMA_VERSION = 2024; /** * Checks if the given regular expression pattern would be valid with the `u` flag. diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 054d89be1d7..11f23cac3d5 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -134,7 +134,10 @@ ruleTester.run("prefer-regex-literals", rule, { { code: "class C { #RegExp; foo() { globalThis.#RegExp('a'); } }", env: { es2020: true } - } + }, + + // ES2024 + "new RegExp('[[A--B]]' + a, 'v')" ], invalid: [ @@ -2808,6 +2811,183 @@ ruleTester.run("prefer-regex-literals", rule, { suggestions: null } ] + }, + + // ES2024 + { + code: "new RegExp('[[A--B]]', 'v')", + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/[[A--B]]/v" + } + ] + } + ] + }, + { + code: "new RegExp('[[A--B]]', 'v')", + parserOptions: { ecmaVersion: 2023 }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: null + } + ] + }, + { + code: "new RegExp('[[A&&&]]', 'v')", + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: null + } + ] + }, + { + code: "new RegExp('a', 'uv')", + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: null + } + ] + }, + { + code: "new RegExp(/a/, 'v')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: [ + { + messageId: "replaceWithLiteralAndFlags", + output: "/a/v", + data: { + flags: "v" + } + } + ] + } + ] + }, + { + code: "new RegExp(/a/, 'v')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2023 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: null + } + ] + }, + { + code: "new RegExp(/a/g, 'v')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: [ + { + messageId: "replaceWithLiteralAndFlags", + output: "/a/v", + data: { + flags: "v" + } + }, + { + messageId: "replaceWithIntendedLiteralAndFlags", + output: "/a/gv", + data: { + flags: "gv" + } + } + ] + } + ] + }, + { + code: "new RegExp(/[[A--B]]/v, 'g')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: [ + { + messageId: "replaceWithIntendedLiteralAndFlags", + output: "/[[A--B]]/vg", + data: { + flags: "vg" + } + } + + // suggestion with flags `g` would be invalid + ] + } + ] + }, + { + code: "new RegExp(/a/u, 'v')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: [ + { + messageId: "replaceWithLiteralAndFlags", + output: "/a/v", + data: { + flags: "v" + } + } + + // suggestion with merged flags `uv` would be invalid + ] + } + ] + }, + { + code: "new RegExp(/a/v, 'u')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: [ + { + messageId: "replaceWithLiteralAndFlags", + output: "/a/u", + data: { + flags: "u" + } + } + + // suggestion with merged flags `vu` would be invalid + ] + } + ] + }, + { + code: "new RegExp(/[[A--B]]/v, 'u')", + options: [{ disallowRedundantWrapping: true }], + parserOptions: { ecmaVersion: 2024 }, + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + suggestions: null + } + ] } ] });