From 3caf51487decdf93a4b17765a2af2a51c337e974 Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Tue, 25 Jul 2023 20:48:58 +0900 Subject: [PATCH] feat: `no-regex-spaces` support `v` flag (#17407) * feat: `no-regex-spaces` support `v` flag * fix: to ignore from check if flag cannot be determined * Apply suggestions from code review Co-authored-by: Milos Djermanovic --------- Co-authored-by: Milos Djermanovic --- lib/rules/no-regex-spaces.js | 21 ++++++++++++++--- tests/lib/rules/no-regex-spaces.js | 38 +++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/rules/no-regex-spaces.js b/lib/rules/no-regex-spaces.js index e7fae6d4055..cb250107289 100644 --- a/lib/rules/no-regex-spaces.js +++ b/lib/rules/no-regex-spaces.js @@ -77,7 +77,7 @@ module.exports = { let regExpAST; try { - regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, flags.includes("u")); + regExpAST = regExpParser.parsePattern(pattern, 0, pattern.length, { unicode: flags.includes("u"), unicodeSets: flags.includes("v") }); } catch { // Ignore regular expressions with syntax errors @@ -155,13 +155,28 @@ module.exports = { const regExpVar = astUtils.getVariableByName(scope, "RegExp"); const shadowed = regExpVar && regExpVar.defs.length > 0; const patternNode = node.arguments[0]; - const flagsNode = node.arguments[1]; if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(patternNode) && !shadowed) { const pattern = patternNode.value; const rawPattern = patternNode.raw.slice(1, -1); const rawPatternStartRange = patternNode.range[0] + 1; - const flags = isString(flagsNode) ? flagsNode.value : ""; + let flags; + + if (node.arguments.length < 2) { + + // It has no flags. + flags = ""; + } else { + const flagsNode = node.arguments[1]; + + if (isString(flagsNode)) { + flags = flagsNode.value; + } else { + + // The flags cannot be determined. + return; + } + } checkRegex( node, diff --git a/tests/lib/rules/no-regex-spaces.js b/tests/lib/rules/no-regex-spaces.js index 89952297549..fdc3eaa1817 100644 --- a/tests/lib/rules/no-regex-spaces.js +++ b/tests/lib/rules/no-regex-spaces.js @@ -62,9 +62,18 @@ ruleTester.run("no-regex-spaces", rule, { "var foo = new RegExp(' \\[ ');", "var foo = new RegExp(' \\[ \\] ');", + // ES2024 + { code: "var foo = / {2}/v;", parserOptions: { ecmaVersion: 2024 } }, + { code: "var foo = /[\\q{ }]/v;", parserOptions: { ecmaVersion: 2024 } }, + // don't report invalid regex "var foo = new RegExp('[ ');", - "var foo = new RegExp('{ ', 'u');" + "var foo = new RegExp('{ ', 'u');", + + // don't report if flags cannot be determined + "new RegExp(' ', flags)", + "new RegExp('[[abc] ]', flags + 'v')", + "new RegExp('[[abc]\\\\q{ }]', flags + 'v')" ], invalid: [ @@ -371,6 +380,33 @@ ruleTester.run("no-regex-spaces", rule, { type: "NewExpression" } ] + }, + + // ES2024 + { + code: "var foo = /[[ ] ] /v;", + output: "var foo = /[[ ] ] {4}/v;", + parserOptions: { + ecmaVersion: 2024 + }, + errors: [ + { + messageId: "multipleSpaces", + data: { length: "4" }, + type: "Literal" + } + ] + }, + { + code: "var foo = new RegExp('[[ ] ] ', 'v');", + output: "var foo = new RegExp('[[ ] ] {4}', 'v');", + errors: [ + { + messageId: "multipleSpaces", + data: { length: "4" }, + type: "NewExpression" + } + ] } ] });