From f7b26d18cbb507a868e7edc2b66515da64d814e2 Mon Sep 17 00:00:00 2001 From: Mathias Schreck Date: Wed, 29 Jan 2020 14:55:19 +0100 Subject: [PATCH] Update: prefer-regex-literal detect regex literals (fixes #12840) The rule `prefer-regex-literal` now detects when regex literals are unnecessarily passed to the `RegExp` constructor. --- lib/rules/prefer-regex-literals.js | 27 ++++++++++++++++++++---- tests/lib/rules/prefer-regex-literals.js | 9 ++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 47b2b090f829..bc5c9497dba1 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -25,6 +25,15 @@ function isStringLiteral(node) { return node.type === "Literal" && typeof node.value === "string"; } +/** + * Determines whether the given node is a regex literal. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a regex literal. + */ +function isRegexLiteral(node) { + return node.type === "Literal" && Object.prototype.hasOwnProperty.call(node, "regex"); +} + /** * Determines whether the given node is a template literal without expressions. * @param {ASTNode} node Node to check. @@ -98,6 +107,15 @@ module.exports = { isStringRawTaggedStaticTemplateLiteral(node); } + /** + * Determines whether the given node is considered to be a static string literal or a regex literal + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a static string or a regex literal + */ + function isStaticPattern(node) { + return isStaticString(node) || isRegexLiteral(node); + } + return { Program() { const scope = context.getScope(); @@ -112,10 +130,11 @@ module.exports = { for (const { node } of tracker.iterateGlobalReferences(traceMap)) { const args = node.arguments; - if ( - (args.length === 1 || args.length === 2) && - args.every(isStaticString) - ) { + if (args.length === 1 && isStaticPattern(args[0])) { + context.report({ node, messageId: "unexpectedRegExp" }); + } + + if (args.length === 2 && isStaticPattern(args[0]) && isStaticString(args[1])) { context.report({ node, messageId: "unexpectedRegExp" }); } } diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index e263ef03dc7a..6a472ebe81bc 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -41,6 +41,7 @@ ruleTester.run("prefer-regex-literals", rule, { "new RegExp(String.raw`a${''}c`);", "new RegExp('a' + 'b')", "RegExp(1)", + "new RegExp(/a/, flags);", // invalid number of arguments "new RegExp;", @@ -177,6 +178,14 @@ ruleTester.run("prefer-regex-literals", rule, { { code: "RegExp('a', String.raw`g`);", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + }, + { + code: "new RegExp(/a/);", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }] + }, + { + code: "new RegExp(/a/, 'u');", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }] } ] });