From bac91cbf8a838d2e5ec3207c6ed2a5b62341c97c Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Wed, 15 Sep 2021 19:08:53 -0700 Subject: [PATCH 01/27] New: Autofix support to prefer-regex-literals Fixes #15029 --- lib/rules/prefer-regex-literals.js | 224 +++++- tests/lib/rules/prefer-regex-literals.js | 854 ++++++++++++++++++++++- 2 files changed, 1034 insertions(+), 44 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index fbfeb5636d7..eca2eaa3e39 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -10,21 +10,13 @@ //------------------------------------------------------------------------------ const astUtils = require("./utils/ast-utils"); -const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils"); +const { CALL, CONSTRUCT, ReferenceTracker, findVariable, getStaticValue } = require("eslint-utils"); +const { validateRegExpLiteral } = require("regexpp"); //------------------------------------------------------------------------------ // Helpers //------------------------------------------------------------------------------ -/** - * Determines whether the given node is a string literal. - * @param {ASTNode} node Node to check. - * @returns {boolean} True if the node is a string literal. - */ -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. @@ -43,6 +35,75 @@ function isStaticTemplateLiteral(node) { return node.type === "TemplateLiteral" && node.expressions.length === 0; } +const validPrecedingTokens = [ + "(", + ";", + "[", + ",", + "=", + "+", + "*", + "-", + "?", + "~", + "%", + "**", + "!", + "typeof", + "instanceof", + "&&", + "||", + "??", + "await", + "yield", + "return", + "...", + "delete", + "void", + "in", + "<", + ">", + "<=", + ">=", + "==", + "===", + "!=", + "!==", + "<<", + ">>", + ">>>", + "&", + "|", + "^", + ":", + "{", + "=>", + "*=", + "<<=", + ">>=", + ">>>=", + "^=", + "|=", + "&=", + "??=", + "||=", + "&&=", + "**=", + "+=", + "-=", + "/=", + "%=", + "/", + "do", + "break", + "continue", + "debugger", + "case", + "throw", + "of", + ")" +]; + //------------------------------------------------------------------------------ // Rule Definition @@ -58,6 +119,8 @@ module.exports = { url: "https://eslint.org/docs/rules/prefer-regex-literals" }, + fixable: "code", + schema: [ { type: "object", @@ -80,6 +143,8 @@ module.exports = { create(context) { const [{ disallowRedundantWrapping = false } = {}] = context.options; + const sourceCode = context.getSourceCode(); + const text = sourceCode.getText(); /** * Determines whether the given identifier node is a reference to a global variable. @@ -107,53 +172,81 @@ module.exports = { } /** - * Determines whether the given node is considered to be a static string by the logic of this rule. - * @param {ASTNode} node Node to check. - * @returns {boolean} True if the node is a static string. + * Gets the value of a string + * @param {ASTNode} node The node to get the string of. + * @param {Scope} [scope] The scope + * @returns {string} The value of the node. */ - function isStaticString(node) { - return isStringLiteral(node) || - isStaticTemplateLiteral(node) || - isStringRawTaggedStaticTemplateLiteral(node); - } + function getStringValue(node, scope) { + const result = getStaticValue(node, scope); - /** - * Determines whether the relevant arguments of the given are all static string literals. - * @param {ASTNode} node Node to check. - * @returns {boolean} True if all arguments are static strings. - */ - function hasOnlyStaticStringArguments(node) { - const args = node.arguments; - - if ((args.length === 1 || args.length === 2) && args.every(isStaticString)) { - return true; + if (result && typeof result.value === "string") { + return result.value; } - - return false; + return null; } /** * Determines whether the arguments of the given node indicate that a regex literal is unnecessarily wrapped. * @param {ASTNode} node Node to check. + * @param {Scope} scope The scope passed to getStringValue * @returns {boolean} True if the node already contains a regex literal argument. */ - function isUnnecessarilyWrappedRegexLiteral(node) { + function isUnnecessarilyWrappedRegexLiteral(node, scope) { const args = node.arguments; if (args.length === 1 && isRegexLiteral(args[0])) { return true; } - if (args.length === 2 && isRegexLiteral(args[0]) && isStaticString(args[1])) { + if (args.length === 2 && isRegexLiteral(args[0]) && getStringValue(args[1], scope)) { return true; } return false; } + /* eslint-disable jsdoc/valid-types -- eslint-plugin-jsdoc's type parser doesn't support square brackets */ + /** + * Returns a ecmaVersion compatible for regexpp. + * @param {import("../linter/linter").ParserOptions["ecmaVersion"]} ecmaVersion The ecmaVersion to convert. + * @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp. + */ + function getRegexppEcmaVersion(ecmaVersion) { + /* eslint-enable jsdoc/valid-types -- JSDoc is over, enable jsdoc/valid-types again */ + if (ecmaVersion === 3 || ecmaVersion === 5) { + return 5; + } + return ecmaVersion + 2009; + } + + /** + * Ensures that String is the only variable present in all child scopes + * @param {Scope} scope The scope to go within and remove variables from + * @param {boolean} [children] Whether to iterate over children or not and if false iterate through parents + * @returns {Scope} The newer scope with only String present + */ + function noStringScope(scope, children = true) { + scope.variables.filter(variable => variable.name !== "String").forEach(definedVariable => scope.set.delete(definedVariable.name)); + if (children) { + for (const childScopeIndex in scope.childScopes) { + if (!isNaN(+childScopeIndex)) { + scope.childScopes[childScopeIndex] = noStringScope(scope.childScopes[childScopeIndex]); + } + } + if (scope.childScopes.length === 0 && scope.upper) { + scope.upper = noStringScope(scope.upper, false); + } + } else if (scope.upper) { + scope.upper = noStringScope(scope.upper, false); + } + return scope; + } + return { Program() { - const scope = context.getScope(); + let scope = context.getScope(); + const tracker = new ReferenceTracker(scope); const traceMap = { RegExp: { @@ -163,14 +256,69 @@ module.exports = { }; for (const { node } of tracker.iterateGlobalReferences(traceMap)) { - if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node)) { + scope = noStringScope(scope); + + if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node, scope)) { if (node.arguments.length === 2) { - context.report({ node, messageId: "unexpectedRedundantRegExpWithFlags" }); + context.report({ + node, + messageId: "unexpectedRedundantRegExpWithFlags", + // eslint-disable-next-line no-loop-func -- scope value won't change + fix(fixer) { + return fixer.replaceTextRange(node.range, node.arguments[0].raw + getStringValue(node.arguments[1], scope)); + } + }); } else { - context.report({ node, messageId: "unexpectedRedundantRegExp" }); + context.report({ + node, + messageId: "unexpectedRedundantRegExp", + fix(fixer) { + return fixer.replaceTextRange(node.range, node.arguments[0].raw); + } + }); } - } else if (hasOnlyStaticStringArguments(node)) { - context.report({ node, messageId: "unexpectedRegExp" }); + } else if ( + (getStringValue(node.arguments[0], scope) !== null) && + (!node.arguments[1] || getStringValue(node.arguments[1], scope) !== null) && + (node.arguments.length === 1 || node.arguments.length === 2) + ) { + let regexContent = getStringValue(node.arguments[0], scope); + + if (regexContent && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { + regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v"); + } + + const newRegExpValue = `/${regexContent || "(?:)"}/${getStringValue(node.arguments[1], scope) || ""}`; + + let noFix = false; + + try { + validateRegExpLiteral( + newRegExpValue, + { ecmaVersion: getRegexppEcmaVersion(context.parserOptions.ecmaVersion) } + ); + } catch { + noFix = true; + } + + const tokenBefore = sourceCode.getTokenBefore(node); + + if (tokenBefore && !validPrecedingTokens.includes(tokenBefore.value)) { + noFix = true; + } + + context.report({ + node, + messageId: "unexpectedRegExp", + ...(noFix ? {} : { + fix(fixer) { + return fixer.replaceTextRange( + node.range, + (text[node.range[0] - 1] === "/" ? " " : "") + newRegExpValue + (["in", "instanceof"].includes((sourceCode.getTokenAfter(node) || {}).value) && text[node.range[1]] === "i" ? " " : "") + ); + } + }) + }); } } } diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index ccd88ae74fd..9d11af3407f 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -33,17 +33,12 @@ ruleTester.run("prefer-regex-literals", rule, { "RegExp(`a` + suffix);", "new RegExp(String.raw`a` + suffix);", "RegExp('a', flags)", + "const flags = 'gu';RegExp('a', flags)", "RegExp('a', 'g' + flags)", "new RegExp(String.raw`a`, flags);", "RegExp(`${prefix}abc`)", "new RegExp(`a${b}c`);", - "new RegExp(`a${''}c`);", "new RegExp(String.raw`a${b}c`);", - "new RegExp(String.raw`a${''}c`);", - "new RegExp('a' + 'b')", - "RegExp(1)", - "new RegExp(/a/, 'u');", - "new RegExp(/a/);", { code: "new RegExp(/a/, flags);", options: [{ disallowRedundantWrapping: true }] @@ -134,116 +129,164 @@ ruleTester.run("prefer-regex-literals", rule, { invalid: [ { code: "new RegExp('abc');", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp('abc');", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp('abc', 'g');", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp('abc', 'g');", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(`abc`);", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp(`abc`);", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(`abc`, `g`);", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp(`abc`, `g`);", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(String.raw`abc`);", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp(String.raw`abc`);", + output: "/abc/;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(String.raw`abc`, String.raw`g`);", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp(String.raw`abc`, String.raw`g`);", + output: "/abc/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(String['raw']`a`);", + output: "/a/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "new RegExp('');", + output: "/(?:)/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp('', '');", + output: "/(?:)/;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(String.raw``);", + output: "/(?:)/;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "new RegExp('a', `g`);", + output: "/a/g;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp(`a`, 'g');", + output: "/a/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "RegExp(String.raw`a`, 'g');", + output: "/a/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(String.raw`\\d`, `g`);", + output: "/\\d/g;", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "new RegExp(String.raw`\\\\d`, `g`);", + output: "/\\\\d/g;", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "new RegExp(String['raw']`\\\\d`, `g`);", + output: "/\\\\d/g;", + errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + }, + { + code: "new RegExp(String[\"raw\"]`\\\\d`, `g`);", + output: "/\\\\d/g;", errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "RegExp('a', String.raw`g`);", + output: "/a/g;", errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new globalThis.RegExp('a');", + output: "/a/;", env: { es2020: true }, errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] }, { code: "globalThis.RegExp('a');", + output: "/a/;", env: { es2020: true }, errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] }, { code: "new RegExp(/a/);", + output: "/a/;", options: [{ disallowRedundantWrapping: true }], errors: [{ messageId: "unexpectedRedundantRegExp", type: "NewExpression", line: 1, column: 1 }] }, { code: "new RegExp(/a/, 'u');", + output: "/a/u;", options: [{ disallowRedundantWrapping: true }], errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] }, { code: "new RegExp(/a/, `u`);", + output: "/a/u;", + options: [{ disallowRedundantWrapping: true }], + errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] + }, + { + code: "new RegExp(/a/, String.raw`u`);", + output: "/a/u;", options: [{ disallowRedundantWrapping: true }], errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] }, { code: "new RegExp('a');", + output: "/a/;", options: [{ disallowRedundantWrapping: true }], errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }] }, @@ -251,6 +294,805 @@ ruleTester.run("prefer-regex-literals", rule, { // Optional chaining { code: "new RegExp((String?.raw)`a`);", + output: "/a/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + + { + code: "new RegExp('+');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('*');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('+');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('*');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('+', 'g');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('*', 'g');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('+', 'g');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('*', 'g');", + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('abc', 'u');", + output: null, + parserOptions: { ecmaVersion: 3 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('abc', 'd');", + output: null, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('abc', 'd');", + output: "/abc/d;", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\\\\\', '');", + output: "/\\\\/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\n', '');", + output: "/\\n/;", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\n\\n', '');", + output: "/\\n\\n/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\t', '');", + output: "/\\t/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\t\\t', '');", + output: "/\\t\\t/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\r\\n', '');", + output: "/\\r\\n/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\u1234', 'g')", + output: "/ሴ/g", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\u{1234}', 'g')", + output: "/ሴ/g", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\u{11111}', 'g')", + output: "/𑄑/g", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\v', '');", + output: "/\\v/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\v\\v', '');", + output: "/\\v\\v/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\f', '');", + output: "/\\f/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\f\\f', '');", + output: "/\\f\\f/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\b', '');", + output: "/\\b/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\b\\\\b', '');", + output: "/\\b\\b/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\B\\\\b', '');", + output: "/\\B\\b/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\w', '');", + output: "/\\w/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new globalThis.RegExp('\\\\W', '');", + output: "/\\W/;", + globals: { + globalThis: "readonly" + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\s', '');", + output: "/\\s/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\S', '')", + output: "/\\S/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "globalThis.RegExp('\\\\d', '');", + output: "/\\d/;", + globals: { + globalThis: "readonly" + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "globalThis.RegExp('\\\\D', '')", + output: "/\\D/", + globals: { + globalThis: "readonly" + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "globalThis.RegExp('\\\\\\\\\\\\D', '')", + output: "/\\\\\\D/", + globals: { + globalThis: "readonly" + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\D\\\\D', '')", + output: "/\\D\\D/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new globalThis.RegExp('\\\\0\\\\0', '');", + output: "/\\0\\0/;", + globals: { + globalThis: "writable" + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\0\\\\0', '');", + output: "/\\0\\0/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\0\\\\0\\\\0', '')", + output: "/\\0\\0\\0/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp('\\\\78\\\\126\\\\5934', '')", + output: "/\\78\\126\\5934/", + parserOptions: { ecmaVersion: 2022 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(String.raw`\\78\\126` + '\\\\5934', '' + `g` + '')", + output: "/\\78\\126\\5934/g", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');", + output: "/\\x56\\x78\\x45/;", + env: { + browser: true + }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp(`a${''}c`);", + output: "/ac/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp(String.raw`a${''}c`);", + output: "/ac/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('a' + 'b')", + output: "/ab/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\[' + \"b\\\\]\")", + output: "/\\[b\\]/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\cA' + '')", + output: "/\\cA/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('\\\\p{Emoji_Presentation}\\\\P{Script_Extensions=Latin}' + '', `ug`)", + output: "/\\p{Emoji_Presentation}\\P{Script_Extensions=Latin}/ug", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "a in(RegExp('abc'))", + output: "a in(/abc/)", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`)", + output: "/(\\p{Emoji_Presentation})\\1/ug", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: `x = y + RegExp("foo").test(x) ? bar() : baz()`, + output: null, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "func(new RegExp(String.raw`a${''}c\\d`, 'u'),new RegExp(String.raw`a${''}c\\d`, 'u'))", + output: "func(/ac\\d/u,/ac\\d/u)", + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, + { + code: `x = y; + RegExp("foo").test(x) ? bar() : baz()`, + output: `x = y; + /foo/.test(x) ? bar() : baz()`, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "typeof RegExp(\"foo\")", + output: "typeof /foo/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`) : false", + output: "/foo/ instanceof /blahblah/g ? typeof /(\\p{Emoji_Presentation})\\1/ug : false", + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, + { + code: "[ new RegExp(`someregular`)]", + output: "[ /someregular/]", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: `const totallyValidatesEmails = new RegExp("\\\\S+@(\\\\S+\\\\.)+\\\\S+") + if (typeof totallyValidatesEmails === 'object') { + runSomethingThatExists(Regexp('stuff')) + }`, + output: `const totallyValidatesEmails = /\\S+@(\\S+\\.)+\\S+/ + if (typeof totallyValidatesEmails === 'object') { + runSomethingThatExists(Regexp('stuff')) + }`, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'", + output: "!/^Hey, /u && /jk$/ && ~/^Sup, / || /hi/ + /person/ === -/hi again/ ? 5 * /abc/ : 'notregbutstring'", + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, + { + code: `#!/usr/bin/sh + RegExp("foo")`, + output: `#!/usr/bin/sh + /foo/`, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "async function abc(){await new RegExp(\"foo\")}", + output: "async function abc(){await /foo/}", + parserOptions: { ecmaVersion: 8, sourceType: "module" }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "function* abc(){yield new RegExp(\"foo\")}", + output: "function* abc(){yield /foo/}", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "function* abc(){yield* new RegExp(\"foo\")}", + output: "function* abc(){yield* /foo/}", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "console.log({ ...new RegExp('a') })", + output: "console.log({ .../a/ })", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "delete RegExp('a');", + output: "delete /a/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "void RegExp('a');", + output: "void /a/;", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')", + output: "/\\S+@(\\S+\\.)+\\S+/**/a/", + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, + { + code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')", + output: "/\\S+@(\\S+\\.)+\\S+/%/a/", + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, + { + code: "a in RegExp('abc')", + output: "a in /abc/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ == new RegExp('cba'); + `, + output: ` + /abc/ == /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ === new RegExp('cba'); + `, + output: ` + /abc/ === /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ != new RegExp('cba'); + `, + output: ` + /abc/ != /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ !== new RegExp('cba'); + `, + output: ` + /abc/ !== /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ > new RegExp('cba'); + `, + output: ` + /abc/ > /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ < new RegExp('cba'); + `, + output: ` + /abc/ < /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ >= new RegExp('cba'); + `, + output: ` + /abc/ >= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ <= new RegExp('cba'); + `, + output: ` + /abc/ <= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ << new RegExp('cba'); + `, + output: ` + /abc/ << /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ >> new RegExp('cba'); + `, + output: ` + /abc/ >> /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ >>> new RegExp('cba'); + `, + output: ` + /abc/ >>> /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ ^ new RegExp('cba'); + `, + output: ` + /abc/ ^ /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ & new RegExp('cba'); + `, + output: ` + /abc/ & /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + /abc/ | new RegExp('cba'); + `, + output: ` + /abc/ | /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + null ?? new RegExp('blah') + `, + output: ` + null ?? /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc *= new RegExp('blah') + `, + output: ` + abc *= /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + console.log({a: new RegExp('sup')}) + `, + output: ` + console.log({a: /sup/}) + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + console.log(() => {new RegExp('sup')}) + `, + output: ` + console.log(() => {/sup/}) + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + function abc() {new RegExp('sup')} + `, + output: ` + function abc() {/sup/} + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + function abc() {return new RegExp('sup')} + `, + output: ` + function abc() {return /sup/} + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc <<= new RegExp('cba'); + `, + output: ` + abc <<= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc >>= new RegExp('cba'); + `, + output: ` + abc >>= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc >>>= new RegExp('cba'); + `, + output: ` + abc >>>= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc ^= new RegExp('cba'); + `, + output: ` + abc ^= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc &= new RegExp('cba'); + `, + output: ` + abc &= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc |= new RegExp('cba'); + `, + output: ` + abc |= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc ??= new RegExp('cba'); + `, + output: ` + abc ??= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc &&= new RegExp('cba'); + `, + output: ` + abc &&= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc ||= new RegExp('cba'); + `, + output: ` + abc ||= /cba/; + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc **= new RegExp('blah') + `, + output: ` + abc **= /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc /= new RegExp('blah') + `, + output: ` + abc /= /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc += new RegExp('blah') + `, + output: ` + abc += /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc -= new RegExp('blah') + `, + output: ` + abc -= /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + abc %= new RegExp('blah') + `, + output: ` + abc %= /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + () => new RegExp('blah') + `, + output: ` + () => /blah/ + `, + parserOptions: { ecmaVersion: 2021 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "a/RegExp(\"foo\")in b", + output: "a/ /foo/ in b", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "a/RegExp(\"foo\")instanceof b", + output: "a/ /foo/ instanceof b", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "do RegExp(\"foo\")\nwhile (true);", + output: "do /foo/\nwhile (true);", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "for(let i;i<5;i++) { break\nnew RegExp('search')}", + output: "for(let i;i<5;i++) { break\n/search/}", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "for(let i;i<5;i++) { continue\nnew RegExp('search')}", + output: "for(let i;i<5;i++) { continue\n/search/}", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: ` + switch (value) { + case "possibility": + console.log('possibility matched') + case RegExp('myReg').toString(): + console.log('matches a regexp\\' toString value') + break; + } + `, + output: ` + switch (value) { + case "possibility": + console.log('possibility matched') + case /myReg/.toString(): + console.log('matches a regexp\\' toString value') + break; + } + `, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "throw new RegExp('abcdefg') // fail with a regular expression", + output: "throw /abcdefg/ // fail with a regular expression", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "for (value of new RegExp('something being searched')) { console.log(value) }", + output: "for (value of /something being searched/) { console.log(value) }", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()", + output: "(async function(){for await (value of /something being searched/) { console.log(value) }})()", + parserOptions: { ecmaVersion: 2018 }, + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "for (value in new RegExp('something being searched')) { console.log(value) }", + output: "for (value in /something being searched/) { console.log(value) }", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "if (condition1 && condition2) new RegExp('avalue').test(str);", + output: "if (condition1 && condition2) /avalue/.test(str);", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "debugger\nnew RegExp('myReg')", + output: "debugger\n/myReg/", errors: [{ messageId: "unexpectedRegExp" }] } ] From 52e6e0052ae1660c4693dc56e5ea0f5987a0083c Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 17 Sep 2021 14:50:43 -0700 Subject: [PATCH 02/27] Use canTokensBeAdjacent --- lib/rules/prefer-regex-literals.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index eca2eaa3e39..0c31a995631 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -12,6 +12,7 @@ const astUtils = require("./utils/ast-utils"); const { CALL, CONSTRUCT, ReferenceTracker, findVariable, getStaticValue } = require("eslint-utils"); const { validateRegExpLiteral } = require("regexpp"); +const { canTokensBeAdjacent } = require("./utils/ast-utils"); //------------------------------------------------------------------------------ // Helpers @@ -312,9 +313,13 @@ module.exports = { messageId: "unexpectedRegExp", ...(noFix ? {} : { fix(fixer) { + const tokenAfter = sourceCode.getTokenAfter(node); + return fixer.replaceTextRange( node.range, - (text[node.range[0] - 1] === "/" ? " " : "") + newRegExpValue + (["in", "instanceof"].includes((sourceCode.getTokenAfter(node) || {}).value) && text[node.range[1]] === "i" ? " " : "") + (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && /\S/u.test(text[node.range[0] - 1]) ? " " : "") + + newRegExpValue + + (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && /\S/u.test(text[node.range[1]]) ? " " : "") ); } }) From 9ce5f47340310762dd185382150aacdff4e7a94b Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sun, 19 Sep 2021 17:14:52 -0700 Subject: [PATCH 03/27] Fix for NULL --- lib/rules/prefer-regex-literals.js | 2 +- tests/lib/rules/prefer-regex-literals.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 0c31a995631..5578615fbc3 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -286,7 +286,7 @@ module.exports = { let regexContent = getStringValue(node.arguments[0], scope); if (regexContent && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { - regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v"); + regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v").replace(/\0/gu, "\\0"); } const newRegExpValue = `/${regexContent || "(?:)"}/${getStringValue(node.arguments[1], scope) || ""}`; diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 9d11af3407f..4f6dcb54386 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -502,6 +502,11 @@ ruleTester.run("prefer-regex-literals", rule, { output: "/\\0\\0/;", errors: [{ messageId: "unexpectedRegExp" }] }, + { + code: "new RegExp('\\0\\0', 'g');", + output: "/\\0\\0/g;", + errors: [{ messageId: "unexpectedRegExp" }] + }, { code: "RegExp('\\\\0\\\\0\\\\0', '')", output: "/\\0\\0\\0/", From f2d582c24fd23cd85a138e4a3fdbb7c91b9ba892 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sun, 19 Sep 2021 17:34:33 -0700 Subject: [PATCH 04/27] Switch to validatePattern and validateFlags --- lib/rules/prefer-regex-literals.js | 26 +++++++++++++++--------- tests/lib/rules/prefer-regex-literals.js | 2 +- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 5578615fbc3..a07b83b02a6 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -11,7 +11,7 @@ const astUtils = require("./utils/ast-utils"); const { CALL, CONSTRUCT, ReferenceTracker, findVariable, getStaticValue } = require("eslint-utils"); -const { validateRegExpLiteral } = require("regexpp"); +const { RegExpValidator } = require("regexpp"); const { canTokensBeAdjacent } = require("./utils/ast-utils"); //------------------------------------------------------------------------------ @@ -284,20 +284,20 @@ module.exports = { (node.arguments.length === 1 || node.arguments.length === 2) ) { let regexContent = getStringValue(node.arguments[0], scope); + let noFix = false; + let flags; - if (regexContent && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { - regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v").replace(/\0/gu, "\\0"); + if (node.arguments[1]) { + flags = getStringValue(node.arguments[1], scope); } - const newRegExpValue = `/${regexContent || "(?:)"}/${getStringValue(node.arguments[1], scope) || ""}`; - - let noFix = false; + const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: getRegexppEcmaVersion(context.parserOptions.ecmaVersion) }); try { - validateRegExpLiteral( - newRegExpValue, - { ecmaVersion: getRegexppEcmaVersion(context.parserOptions.ecmaVersion) } - ); + RegExpValidatorInstance.validatePattern(regexContent); + if (flags) { + RegExpValidatorInstance.validateFlags(flags); + } } catch { noFix = true; } @@ -308,6 +308,12 @@ module.exports = { noFix = true; } + if (regexContent && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { + regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v").replace(/\0/gu, "\\0"); + } + + const newRegExpValue = `/${regexContent || "(?:)"}/${flags || ""}`; + context.report({ node, messageId: "unexpectedRegExp", diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 4f6dcb54386..60235975a17 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -345,7 +345,7 @@ ruleTester.run("prefer-regex-literals", rule, { errors: [{ messageId: "unexpectedRegExp" }] }, { - code: "RegExp('abc', 'd');", + code: "new RegExp('abc', 'd');", output: null, parserOptions: { ecmaVersion: 2021 }, errors: [{ messageId: "unexpectedRegExp" }] From ac05a369e16e901d9cb5c0ba3363f59f5c23f8cd Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sun, 19 Sep 2021 17:50:01 -0700 Subject: [PATCH 05/27] Fix for unicode --- lib/rules/prefer-regex-literals.js | 4 ++++ tests/lib/rules/prefer-regex-literals.js | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index a07b83b02a6..ec5618fbfb0 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -308,6 +308,10 @@ module.exports = { noFix = true; } + if (!/^[-\na-zA-Z\0\r\v\f0-9\\[\](){}\s!@#$%^&*+^_=/~`.> Date: Fri, 24 Sep 2021 12:41:29 -0700 Subject: [PATCH 06/27] Apply a few suggestions from code review --- lib/rules/prefer-regex-literals.js | 10 +++------- tests/lib/rules/prefer-regex-literals.js | 15 ++++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index ec5618fbfb0..761a1dcf7dc 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -55,8 +55,6 @@ const validPrecedingTokens = [ "&&", "||", "??", - "await", - "yield", "return", "...", "delete", @@ -100,9 +98,7 @@ const validPrecedingTokens = [ "continue", "debugger", "case", - "throw", - "of", - ")" + "throw" ]; @@ -215,7 +211,7 @@ module.exports = { */ function getRegexppEcmaVersion(ecmaVersion) { /* eslint-enable jsdoc/valid-types -- JSDoc is over, enable jsdoc/valid-types again */ - if (ecmaVersion === 3 || ecmaVersion === 5) { + if (!ecmaVersion || ecmaVersion > 13 || ecmaVersion === 3 || ecmaVersion === 5) { return 5; } return ecmaVersion + 2009; @@ -294,7 +290,7 @@ module.exports = { const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: getRegexppEcmaVersion(context.parserOptions.ecmaVersion) }); try { - RegExpValidatorInstance.validatePattern(regexContent); + RegExpValidatorInstance.validatePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); if (flags) { RegExpValidatorInstance.validateFlags(flags); } diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 23e0cc6c830..cbb5cdcdad6 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -582,6 +582,11 @@ ruleTester.run("prefer-regex-literals", rule, { output: "func(/ac\\d/u,/ac\\d/u)", errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] }, + { + code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))", + output: null, + errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + }, { code: `x = y; RegExp("foo").test(x) ? bar() : baz()`, @@ -629,13 +634,13 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "async function abc(){await new RegExp(\"foo\")}", - output: "async function abc(){await /foo/}", + output: null, parserOptions: { ecmaVersion: 8, sourceType: "module" }, errors: [{ messageId: "unexpectedRegExp" }] }, { code: "function* abc(){yield new RegExp(\"foo\")}", - output: "function* abc(){yield /foo/}", + output: null, errors: [{ messageId: "unexpectedRegExp" }] }, { @@ -1076,12 +1081,12 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "for (value of new RegExp('something being searched')) { console.log(value) }", - output: "for (value of /something being searched/) { console.log(value) }", + output: null, errors: [{ messageId: "unexpectedRegExp" }] }, { code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()", - output: "(async function(){for await (value of /something being searched/) { console.log(value) }})()", + output: null, parserOptions: { ecmaVersion: 2018 }, errors: [{ messageId: "unexpectedRegExp" }] }, @@ -1092,7 +1097,7 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "if (condition1 && condition2) new RegExp('avalue').test(str);", - output: "if (condition1 && condition2) /avalue/.test(str);", + output: null, errors: [{ messageId: "unexpectedRegExp" }] }, { From 9e3b7e2c7e05655ca048f21493b62cbe86172d5c Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 24 Sep 2021 17:06:17 -0700 Subject: [PATCH 07/27] Fix: Double Escaping? --- lib/rules/prefer-regex-literals.js | 68 ++++++++++++++++++++++-- tests/lib/rules/prefer-regex-literals.js | 25 +++++++++ 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 761a1dcf7dc..3292c11bc5b 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -11,7 +11,7 @@ const astUtils = require("./utils/ast-utils"); const { CALL, CONSTRUCT, ReferenceTracker, findVariable, getStaticValue } = require("eslint-utils"); -const { RegExpValidator } = require("regexpp"); +const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp"); const { canTokensBeAdjacent } = require("./utils/ast-utils"); //------------------------------------------------------------------------------ @@ -240,6 +240,36 @@ module.exports = { return scope; } + /** + * Makes a character escaped or else returns null + * @param {string & {length:1}} character The character to escape + * @returns {string} The resulting escaped character + */ + function resolveEscapes(character) { + switch (character) { + case "\n": + return "\\n"; + + case "\r": + return "\\r"; + + case "\t": + return "\\t"; + + case "\v": + return "\\v"; + + case "\f": + return "\\f"; + + case "\0": + return "\\0"; + + default: + return null; + } + } + return { Program() { let scope = context.getScope(); @@ -287,7 +317,8 @@ module.exports = { flags = getStringValue(node.arguments[1], scope); } - const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: getRegexppEcmaVersion(context.parserOptions.ecmaVersion) }); + const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion); + const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion }); try { RegExpValidatorInstance.validatePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); @@ -308,8 +339,37 @@ module.exports = { noFix = true; } - if (regexContent && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { - regexContent = regexContent.replace(/\r/gu, "\\r").replace(/\n/gu, "\\n").replace(/\t/gu, "\\t").replace(/\f/gu, "\\f").replace(/\v/gu, "\\v").replace(/\0/gu, "\\0"); + if (regexContent && !noFix && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { + let charIncrease = 0; + + const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); + + visitRegExpAST(ast, { + onCharacterEnter(characterNode) { + let changeCharIncrease = true; + let stringCodePointValue = String.fromCodePoint(characterNode.value); + const escaped = resolveEscapes(stringCodePointValue); + + if (escaped) { + stringCodePointValue = escaped; + } else { + changeCharIncrease = false; + } + + if (characterNode.value === 0 && characterNode.raw !== "\0") { + changeCharIncrease = false; + } + + regexContent = + regexContent.slice(0, characterNode.start + charIncrease) + + (escaped ? stringCodePointValue : characterNode.raw) + + regexContent.slice(characterNode.end + charIncrease); + + if (changeCharIncrease) { + charIncrease++; + } + } + }); } const newRegExpValue = `/${regexContent || "(?:)"}/${flags || ""}`; diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index cbb5cdcdad6..3a9a53884d6 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -1104,6 +1104,31 @@ ruleTester.run("prefer-regex-literals", rule, { code: "debugger\nnew RegExp('myReg')", output: "debugger\n/myReg/", errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"\\\\\\n\")", + output: "/\\n/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"\\\\\\t\")", + output: "/\\t/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"\\\\\\f\")", + output: "/\\f/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"\\\\\\v\")", + output: "/\\v/", + errors: [{ messageId: "unexpectedRegExp" }] + }, + { + code: "RegExp(\"\\\\\\r\")", + output: "/\\r/", + errors: [{ messageId: "unexpectedRegExp" }] } ] }); From 45137006a17d612ba3c7b1ba268b2c9ef41601d2 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 24 Sep 2021 17:15:33 -0700 Subject: [PATCH 08/27] Tests and fixes for no-unicode regexp --- lib/rules/prefer-regex-literals.js | 5 ++++- tests/lib/rules/prefer-regex-literals.js | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 3292c11bc5b..1be5876c7af 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -265,6 +265,9 @@ module.exports = { case "\0": return "\\0"; + case "/": + return "\\/"; + default: return null; } @@ -335,7 +338,7 @@ module.exports = { noFix = true; } - if (!/^[-\na-zA-Z\0\r\v\f0-9\\[\](){}\s!@#$%^&*+^_=/~`.> Date: Fri, 24 Sep 2021 17:34:35 -0700 Subject: [PATCH 09/27] New: Drop usage of getStaticValue --- lib/rules/prefer-regex-literals.js | 109 ++++++++++++----------- tests/lib/rules/prefer-regex-literals.js | 57 +++--------- 2 files changed, 69 insertions(+), 97 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 1be5876c7af..f4feb24771a 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -10,7 +10,7 @@ //------------------------------------------------------------------------------ const astUtils = require("./utils/ast-utils"); -const { CALL, CONSTRUCT, ReferenceTracker, findVariable, getStaticValue } = require("eslint-utils"); +const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils"); const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp"); const { canTokensBeAdjacent } = require("./utils/ast-utils"); @@ -18,6 +18,15 @@ const { canTokensBeAdjacent } = require("./utils/ast-utils"); // Helpers //------------------------------------------------------------------------------ +/** + * Determines whether the given node is a string literal. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a string literal. + */ +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. @@ -171,32 +180,60 @@ module.exports = { /** * Gets the value of a string * @param {ASTNode} node The node to get the string of. - * @param {Scope} [scope] The scope - * @returns {string} The value of the node. + * @returns {string|null} The value of the node. */ - function getStringValue(node, scope) { - const result = getStaticValue(node, scope); - - if (result && typeof result.value === "string") { - return result.value; + function getStringValue(node) { + if (isStringLiteral(node)) { + return node.value; + // eslint-disable-next-line no-else-return -- No need for unnecessary cyclomatic complexity + } else if (isStaticTemplateLiteral(node)) { + return node.quasis[0].value.cooked; + } else if (isStringRawTaggedStaticTemplateLiteral(node)) { + return node.quasi.quasis[0].value.raw; } + return null; } + /** + * Determines whether the given node is considered to be a static string by the logic of this rule. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if the node is a static string. + */ + function isStaticString(node) { + return isStringLiteral(node) || + isStaticTemplateLiteral(node) || + isStringRawTaggedStaticTemplateLiteral(node); + } + + /** + * Determines whether the relevant arguments of the given are all static string literals. + * @param {ASTNode} node Node to check. + * @returns {boolean} True if all arguments are static strings. + */ + function hasOnlyStaticStringArguments(node) { + const args = node.arguments; + + if ((args.length === 1 || args.length === 2) && args.every(isStaticString)) { + return true; + } + + return false; + } + /** * Determines whether the arguments of the given node indicate that a regex literal is unnecessarily wrapped. * @param {ASTNode} node Node to check. - * @param {Scope} scope The scope passed to getStringValue * @returns {boolean} True if the node already contains a regex literal argument. */ - function isUnnecessarilyWrappedRegexLiteral(node, scope) { + function isUnnecessarilyWrappedRegexLiteral(node) { const args = node.arguments; if (args.length === 1 && isRegexLiteral(args[0])) { return true; } - if (args.length === 2 && isRegexLiteral(args[0]) && getStringValue(args[1], scope)) { + if (args.length === 2 && isRegexLiteral(args[0]) && isStaticString(args[1])) { return true; } @@ -218,32 +255,9 @@ module.exports = { } /** - * Ensures that String is the only variable present in all child scopes - * @param {Scope} scope The scope to go within and remove variables from - * @param {boolean} [children] Whether to iterate over children or not and if false iterate through parents - * @returns {Scope} The newer scope with only String present - */ - function noStringScope(scope, children = true) { - scope.variables.filter(variable => variable.name !== "String").forEach(definedVariable => scope.set.delete(definedVariable.name)); - if (children) { - for (const childScopeIndex in scope.childScopes) { - if (!isNaN(+childScopeIndex)) { - scope.childScopes[childScopeIndex] = noStringScope(scope.childScopes[childScopeIndex]); - } - } - if (scope.childScopes.length === 0 && scope.upper) { - scope.upper = noStringScope(scope.upper, false); - } - } else if (scope.upper) { - scope.upper = noStringScope(scope.upper, false); - } - return scope; - } - - /** - * Makes a character escaped or else returns null - * @param {string & {length:1}} character The character to escape - * @returns {string} The resulting escaped character + * Makes a character escaped or else returns null. + * @param {string & {length:1}} character The character to escape. + * @returns {string} The resulting escaped character. */ function resolveEscapes(character) { switch (character) { @@ -275,8 +289,7 @@ module.exports = { return { Program() { - let scope = context.getScope(); - + const scope = context.getScope(); const tracker = new ReferenceTracker(scope); const traceMap = { RegExp: { @@ -286,16 +299,14 @@ module.exports = { }; for (const { node } of tracker.iterateGlobalReferences(traceMap)) { - scope = noStringScope(scope); - - if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node, scope)) { + if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node)) { if (node.arguments.length === 2) { context.report({ node, messageId: "unexpectedRedundantRegExpWithFlags", - // eslint-disable-next-line no-loop-func -- scope value won't change + fix(fixer) { - return fixer.replaceTextRange(node.range, node.arguments[0].raw + getStringValue(node.arguments[1], scope)); + return fixer.replaceTextRange(node.range, node.arguments[0].raw + getStringValue(node.arguments[1])); } }); } else { @@ -307,17 +318,13 @@ module.exports = { } }); } - } else if ( - (getStringValue(node.arguments[0], scope) !== null) && - (!node.arguments[1] || getStringValue(node.arguments[1], scope) !== null) && - (node.arguments.length === 1 || node.arguments.length === 2) - ) { - let regexContent = getStringValue(node.arguments[0], scope); + } else if (hasOnlyStaticStringArguments(node)) { + let regexContent = getStringValue(node.arguments[0]); let noFix = false; let flags; if (node.arguments[1]) { - flags = getStringValue(node.arguments[1], scope); + flags = getStringValue(node.arguments[1]); } const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index eb3e1f4658a..00b41aa45dd 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -26,6 +26,8 @@ ruleTester.run("prefer-regex-literals", rule, { // considered as dynamic "new RegExp(pattern)", + "new RegExp('\\\\p{Emoji_Presentation}\\\\P{Script_Extensions=Latin}' + '', `ug`)", + "new RegExp('\\\\cA' + '')", "RegExp(pattern, 'g')", "new RegExp(f('a'))", "RegExp(prefix + 'a')", @@ -39,6 +41,14 @@ ruleTester.run("prefer-regex-literals", rule, { "RegExp(`${prefix}abc`)", "new RegExp(`a${b}c`);", "new RegExp(String.raw`a${b}c`);", + "new RegExp(`a${''}c`);", + "new RegExp(String.raw`a${''}c`);", + "new RegExp('a' + 'b')", + "RegExp(1)", + "new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`)", + "RegExp(String.raw`\\78\\126` + '\\\\5934', '' + `g` + '')", + "func(new RegExp(String.raw`a${''}c\\d`, 'u'),new RegExp(String.raw`a${''}c\\d`, 'u'))", + "new RegExp('\\\\[' + \"b\\\\]\")", { code: "new RegExp(/a/, flags);", options: [{ disallowRedundantWrapping: true }] @@ -518,11 +528,6 @@ ruleTester.run("prefer-regex-literals", rule, { parserOptions: { ecmaVersion: 2022 }, errors: [{ messageId: "unexpectedRegExp" }] }, - { - code: "RegExp(String.raw`\\78\\126` + '\\\\5934', '' + `g` + '')", - output: "/\\78\\126\\5934/g", - errors: [{ messageId: "unexpectedRegExp" }] - }, { code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');", output: "/\\x56\\x78\\x45/;", @@ -531,57 +536,17 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [{ messageId: "unexpectedRegExp" }] }, - { - code: "new RegExp(`a${''}c`);", - output: "/ac/;", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: "new RegExp(String.raw`a${''}c`);", - output: "/ac/;", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: "new RegExp('a' + 'b')", - output: "/ab/", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: "new RegExp('\\\\[' + \"b\\\\]\")", - output: "/\\[b\\]/", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: "new RegExp('\\\\cA' + '')", - output: "/\\cA/", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: "new RegExp('\\\\p{Emoji_Presentation}\\\\P{Script_Extensions=Latin}' + '', `ug`)", - output: "/\\p{Emoji_Presentation}\\P{Script_Extensions=Latin}/ug", - errors: [{ messageId: "unexpectedRegExp" }] - }, { code: "a in(RegExp('abc'))", output: "a in(/abc/)", errors: [{ messageId: "unexpectedRegExp" }] }, - { - code: "new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`)", - output: "/(\\p{Emoji_Presentation})\\1/ug", - errors: [{ messageId: "unexpectedRegExp" }] - }, { code: `x = y RegExp("foo").test(x) ? bar() : baz()`, output: null, errors: [{ messageId: "unexpectedRegExp" }] }, - { - code: "func(new RegExp(String.raw`a${''}c\\d`, 'u'),new RegExp(String.raw`a${''}c\\d`, 'u'))", - output: "func(/ac\\d/u,/ac\\d/u)", - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] - }, { code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))", output: null, @@ -600,7 +565,7 @@ ruleTester.run("prefer-regex-literals", rule, { errors: [{ messageId: "unexpectedRegExp" }] }, { - code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1' + '', `ug`) : false", + code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false", output: "/foo/ instanceof /blahblah/g ? typeof /(\\p{Emoji_Presentation})\\1/ug : false", errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] }, From 06109bac3c2898363f1076e2b7c029ad732aa221 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sat, 25 Sep 2021 15:07:44 -0700 Subject: [PATCH 10/27] Fix: Remove whitespace changes, fix jsdoc type, and convert to suggestion for unexpectedRegExp --- lib/rules/prefer-regex-literals.js | 15 +- tests/lib/rules/prefer-regex-literals.js | 2518 ++++++++++++++++------ 2 files changed, 1920 insertions(+), 613 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index f4feb24771a..683ee35ffa2 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -122,10 +122,12 @@ module.exports = { docs: { description: "disallow use of the `RegExp` constructor in favor of regular expression literals", recommended: false, - url: "https://eslint.org/docs/rules/prefer-regex-literals" + url: "https://eslint.org/docs/rules/prefer-regex-literals", + suggestion: true }, fixable: "code", + hasSuggestions: true, schema: [ { @@ -202,8 +204,8 @@ module.exports = { */ function isStaticString(node) { return isStringLiteral(node) || - isStaticTemplateLiteral(node) || - isStringRawTaggedStaticTemplateLiteral(node); + isStaticTemplateLiteral(node) || + isStringRawTaggedStaticTemplateLiteral(node); } /** @@ -256,7 +258,7 @@ module.exports = { /** * Makes a character escaped or else returns null. - * @param {string & {length:1}} character The character to escape. + * @param {string} character The character to escape. * @returns {string} The resulting escaped character. */ function resolveEscapes(character) { @@ -387,7 +389,8 @@ module.exports = { context.report({ node, messageId: "unexpectedRegExp", - ...(noFix ? {} : { + suggest: noFix ? [] : [{ + messageId: "unexpectedRegExp", fix(fixer) { const tokenAfter = sourceCode.getTokenAfter(node); @@ -398,7 +401,7 @@ module.exports = { (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && /\S/u.test(text[node.range[1]]) ? " " : "") ); } - }) + }] }); } } diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 00b41aa45dd..aa30726ecf1 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -40,8 +40,8 @@ ruleTester.run("prefer-regex-literals", rule, { "new RegExp(String.raw`a`, flags);", "RegExp(`${prefix}abc`)", "new RegExp(`a${b}c`);", - "new RegExp(String.raw`a${b}c`);", "new RegExp(`a${''}c`);", + "new RegExp(String.raw`a${b}c`);", "new RegExp(String.raw`a${''}c`);", "new RegExp('a' + 'b')", "RegExp(1)", @@ -139,971 +139,2275 @@ ruleTester.run("prefer-regex-literals", rule, { invalid: [ { code: "new RegExp('abc');", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "RegExp('abc');", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "new RegExp('abc', 'g');", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "RegExp('abc', 'g');", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "new RegExp(`abc`);", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "RegExp(`abc`);", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "new RegExp(`abc`, `g`);", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "RegExp(`abc`, `g`);", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "new RegExp(String.raw`abc`);", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "RegExp(String.raw`abc`);", - output: "/abc/;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/;" + } + ] + } + ] }, { code: "new RegExp(String.raw`abc`, String.raw`g`);", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "RegExp(String.raw`abc`, String.raw`g`);", - output: "/abc/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/g;" + } + ] + } + ] }, { code: "new RegExp(String['raw']`a`);", - output: "/a/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/;" + } + ] + } + ] }, { code: "new RegExp('');", - output: "/(?:)/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/(?:)/;" + } + ] + } + ] }, { code: "RegExp('', '');", - output: "/(?:)/;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/(?:)/;" + } + ] + } + ] }, { code: "new RegExp(String.raw``);", - output: "/(?:)/;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/(?:)/;" + } + ] + } + ] }, { code: "new RegExp('a', `g`);", - output: "/a/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/g;" + } + ] + } + ] }, { code: "RegExp(`a`, 'g');", - output: "/a/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/g;" + } + ] + } + ] }, { code: "RegExp(String.raw`a`, 'g');", - output: "/a/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/g;" + } + ] + } + ] }, { code: "new RegExp(String.raw`\\d`, `g`);", - output: "/\\d/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\d/g;" + } + ] + } + ] }, { code: "new RegExp(String.raw`\\\\d`, `g`);", - output: "/\\\\d/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\\\d/g;" + } + ] + } + ] }, { code: "new RegExp(String['raw']`\\\\d`, `g`);", - output: "/\\\\d/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\\\d/g;" + } + ] + } + ] }, { code: "new RegExp(String[\"raw\"]`\\\\d`, `g`);", - output: "/\\\\d/g;", - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\\\d/g;" + } + ] + } + ] }, { code: "RegExp('a', String.raw`g`);", - output: "/a/g;", - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/g;" + } + ] + } + ] }, { code: "new globalThis.RegExp('a');", - output: "/a/;", - env: { es2020: true }, - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }] + output: null, + env: { + es2020: true + }, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/;" + } + ] + } + ] }, { code: "globalThis.RegExp('a');", - output: "/a/;", - env: { es2020: true }, - errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }] + output: null, + env: { + es2020: true + }, + errors: [ + { + messageId: "unexpectedRegExp", + type: "CallExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/;" + } + ] + } + ] }, - { code: "new RegExp(/a/);", output: "/a/;", - options: [{ disallowRedundantWrapping: true }], - errors: [{ messageId: "unexpectedRedundantRegExp", type: "NewExpression", line: 1, column: 1 }] + options: [ + { + disallowRedundantWrapping: true + } + ], + errors: [ + { + messageId: "unexpectedRedundantRegExp", + type: "NewExpression", + line: 1, + column: 1 + } + ] }, { code: "new RegExp(/a/, 'u');", output: "/a/u;", - options: [{ disallowRedundantWrapping: true }], - errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] + options: [ + { + disallowRedundantWrapping: true + } + ], + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + type: "NewExpression", + line: 1, + column: 1 + } + ] }, { code: "new RegExp(/a/, `u`);", output: "/a/u;", - options: [{ disallowRedundantWrapping: true }], - errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] + options: [ + { + disallowRedundantWrapping: true + } + ], + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + type: "NewExpression", + line: 1, + column: 1 + } + ] }, { code: "new RegExp(/a/, String.raw`u`);", output: "/a/u;", - options: [{ disallowRedundantWrapping: true }], - errors: [{ messageId: "unexpectedRedundantRegExpWithFlags", type: "NewExpression", line: 1, column: 1 }] + options: [ + { + disallowRedundantWrapping: true + } + ], + errors: [ + { + messageId: "unexpectedRedundantRegExpWithFlags", + type: "NewExpression", + line: 1, + column: 1 + } + ] }, { code: "new RegExp('a');", - output: "/a/;", - options: [{ disallowRedundantWrapping: true }], - errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }] + output: null, + options: [ + { + disallowRedundantWrapping: true + } + ], + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + line: 1, + column: 1, + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/;" + } + ] + } + ] }, - - // Optional chaining { code: "new RegExp((String?.raw)`a`);", - output: "/a/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/a/;" + } + ] + } + ] }, - { code: "new RegExp('+');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "new RegExp('*');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('+');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('*');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "new RegExp('+', 'g');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "new RegExp('*', 'g');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('+', 'g');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('*', 'g');", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('abc', 'u');", output: null, - parserOptions: { ecmaVersion: 3 }, - errors: [{ messageId: "unexpectedRegExp" }] + parserOptions: { + ecmaVersion: 3 + }, + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "new RegExp('abc', 'd');", output: null, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('abc', 'd');", - output: "/abc/d;", - parserOptions: { ecmaVersion: 2022 }, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + parserOptions: { + ecmaVersion: 2022 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc/d;" + } + ] + } + ] }, { code: "RegExp('\\\\\\\\', '');", - output: "/\\\\/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\\\/;" + } + ] + } + ] }, { code: "RegExp('\\n', '');", - output: "/\\n/;", - parserOptions: { ecmaVersion: 2022 }, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + parserOptions: { + ecmaVersion: 2022 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n/;" + } + ] + } + ] }, { code: "RegExp('\\n\\n', '');", - output: "/\\n\\n/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n\\n/;" + } + ] + } + ] }, { code: "RegExp('\\t', '');", - output: "/\\t/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\t/;" + } + ] + } + ] }, { code: "RegExp('\\t\\t', '');", - output: "/\\t\\t/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\t\\t/;" + } + ] + } + ] }, { code: "RegExp('\\r\\n', '');", - output: "/\\r\\n/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\r\\n/;" + } + ] + } + ] }, { code: "RegExp('\\u1234', 'g')", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('\\u{1234}', 'g')", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('\\u{11111}', 'g')", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "RegExp('\\v', '');", - output: "/\\v/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\v/;" + } + ] + } + ] }, { code: "RegExp('\\v\\v', '');", - output: "/\\v\\v/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\v\\v/;" + } + ] + } + ] }, { code: "RegExp('\\f', '');", - output: "/\\f/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\f/;" + } + ] + } + ] }, { code: "RegExp('\\f\\f', '');", - output: "/\\f\\f/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\f\\f/;" + } + ] + } + ] }, { code: "RegExp('\\\\b', '');", - output: "/\\b/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\b/;" + } + ] + } + ] }, { code: "RegExp('\\\\b\\\\b', '');", - output: "/\\b\\b/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\b\\b/;" + } + ] + } + ] }, { code: "new RegExp('\\\\B\\\\b', '');", - output: "/\\B\\b/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\B\\b/;" + } + ] + } + ] }, { code: "RegExp('\\\\w', '');", - output: "/\\w/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\w/;" + } + ] + } + ] }, { code: "new globalThis.RegExp('\\\\W', '');", - output: "/\\W/;", + output: null, globals: { globalThis: "readonly" }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\W/;" + } + ] + } + ] }, { code: "RegExp('\\\\s', '');", - output: "/\\s/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\s/;" + } + ] + } + ] }, { code: "new RegExp('\\\\S', '')", - output: "/\\S/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\S/" + } + ] + } + ] }, { code: "globalThis.RegExp('\\\\d', '');", - output: "/\\d/;", + output: null, globals: { globalThis: "readonly" }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\d/;" + } + ] + } + ] }, { code: "globalThis.RegExp('\\\\D', '')", - output: "/\\D/", + output: null, globals: { globalThis: "readonly" }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\D/" + } + ] + } + ] }, { code: "globalThis.RegExp('\\\\\\\\\\\\D', '')", - output: "/\\\\\\D/", + output: null, globals: { globalThis: "readonly" }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\\\\\D/" + } + ] + } + ] }, { code: "new RegExp('\\\\D\\\\D', '')", - output: "/\\D\\D/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\D\\D/" + } + ] + } + ] }, { code: "new globalThis.RegExp('\\\\0\\\\0', '');", - output: "/\\0\\0/;", + output: null, globals: { globalThis: "writable" }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\0\\0/;" + } + ] + } + ] }, { code: "new RegExp('\\\\0\\\\0', '');", - output: "/\\0\\0/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\0\\0/;" + } + ] + } + ] }, { code: "new RegExp('\\0\\0', 'g');", - output: "/\\0\\0/g;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\0\\0/g;" + } + ] + } + ] }, { code: "RegExp('\\\\0\\\\0\\\\0', '')", - output: "/\\0\\0\\0/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\0\\0\\0/" + } + ] + } + ] }, { code: "RegExp('\\\\78\\\\126\\\\5934', '')", - output: "/\\78\\126\\5934/", - parserOptions: { ecmaVersion: 2022 }, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + parserOptions: { + ecmaVersion: 2022 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\78\\126\\5934/" + } + ] + } + ] }, { code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');", - output: "/\\x56\\x78\\x45/;", + output: null, env: { browser: true }, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\x56\\x78\\x45/;" + } + ] + } + ] }, { code: "a in(RegExp('abc'))", - output: "a in(/abc/)", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: `x = y - RegExp("foo").test(x) ? bar() : baz()`, output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "a in(/abc/)" + } + ] + } + ] + }, + { + code: "x = y\n RegExp(\"foo\").test(x) ? bar() : baz()", + output: null, + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))", output: null, - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + } + ] }, { - code: `x = y; - RegExp("foo").test(x) ? bar() : baz()`, - output: `x = y; - /foo/.test(x) ? bar() : baz()`, - errors: [{ messageId: "unexpectedRegExp" }] + code: "x = y;\n RegExp(\"foo\").test(x) ? bar() : baz()", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "x = y;\n /foo/.test(x) ? bar() : baz()" + } + ] + } + ] }, { code: "typeof RegExp(\"foo\")", - output: "typeof /foo/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "typeof /foo/" + } + ] + } + ] }, { code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false", - output: "/foo/ instanceof /blahblah/g ? typeof /(\\p{Emoji_Presentation})\\1/ug : false", - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + } + ] }, { code: "[ new RegExp(`someregular`)]", - output: "[ /someregular/]", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: `const totallyValidatesEmails = new RegExp("\\\\S+@(\\\\S+\\\\.)+\\\\S+") - if (typeof totallyValidatesEmails === 'object') { - runSomethingThatExists(Regexp('stuff')) - }`, - output: `const totallyValidatesEmails = /\\S+@(\\S+\\.)+\\S+/ - if (typeof totallyValidatesEmails === 'object') { - runSomethingThatExists(Regexp('stuff')) - }`, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "[ /someregular/]" + } + ] + } + ] + }, + { + code: "const totallyValidatesEmails = new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")\n if (typeof totallyValidatesEmails === 'object') {\n runSomethingThatExists(Regexp('stuff'))\n }", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "const totallyValidatesEmails = /\\S+@(\\S+\\.)+\\S+/\n if (typeof totallyValidatesEmails === 'object') {\n runSomethingThatExists(Regexp('stuff'))\n }" + } + ] + } + ] }, { code: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'", - output: "!/^Hey, /u && /jk$/ && ~/^Sup, / || /hi/ + /person/ === -/hi again/ ? 5 * /abc/ : 'notregbutstring'", - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] - }, - { - code: `#!/usr/bin/sh - RegExp("foo")`, - output: `#!/usr/bin/sh - /foo/`, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + } + ] + }, + { + code: "#!/usr/bin/sh\n RegExp(\"foo\")", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "#!/usr/bin/sh\n /foo/" + } + ] + } + ] }, { code: "async function abc(){await new RegExp(\"foo\")}", output: null, - parserOptions: { ecmaVersion: 8, sourceType: "module" }, - errors: [{ messageId: "unexpectedRegExp" }] + parserOptions: { + ecmaVersion: 8, + sourceType: "module" + }, + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "function* abc(){yield new RegExp(\"foo\")}", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "function* abc(){yield* new RegExp(\"foo\")}", - output: "function* abc(){yield* /foo/}", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "function* abc(){yield* /foo/}" + } + ] + } + ] }, { code: "console.log({ ...new RegExp('a') })", - output: "console.log({ .../a/ })", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "console.log({ .../a/ })" + } + ] + } + ] }, { code: "delete RegExp('a');", - output: "delete /a/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "delete /a/;" + } + ] + } + ] }, { code: "void RegExp('a');", - output: "void /a/;", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "void /a/;" + } + ] + } + ] }, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')", - output: "/\\S+@(\\S+\\.)+\\S+/**/a/", - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + } + ] }, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')", - output: "/\\S+@(\\S+\\.)+\\S+/%/a/", - errors: [{ messageId: "unexpectedRegExp" }, { messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp" + }, + { + messageId: "unexpectedRegExp" + } + ] }, { code: "a in RegExp('abc')", - output: "a in /abc/", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ == new RegExp('cba'); - `, - output: ` - /abc/ == /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ === new RegExp('cba'); - `, - output: ` - /abc/ === /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ != new RegExp('cba'); - `, - output: ` - /abc/ != /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ !== new RegExp('cba'); - `, - output: ` - /abc/ !== /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ > new RegExp('cba'); - `, - output: ` - /abc/ > /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ < new RegExp('cba'); - `, - output: ` - /abc/ < /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ >= new RegExp('cba'); - `, - output: ` - /abc/ >= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ <= new RegExp('cba'); - `, - output: ` - /abc/ <= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ << new RegExp('cba'); - `, - output: ` - /abc/ << /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ >> new RegExp('cba'); - `, - output: ` - /abc/ >> /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ >>> new RegExp('cba'); - `, - output: ` - /abc/ >>> /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ ^ new RegExp('cba'); - `, - output: ` - /abc/ ^ /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ & new RegExp('cba'); - `, - output: ` - /abc/ & /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - /abc/ | new RegExp('cba'); - `, - output: ` - /abc/ | /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - null ?? new RegExp('blah') - `, - output: ` - null ?? /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc *= new RegExp('blah') - `, - output: ` - abc *= /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - console.log({a: new RegExp('sup')}) - `, - output: ` - console.log({a: /sup/}) - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - console.log(() => {new RegExp('sup')}) - `, - output: ` - console.log(() => {/sup/}) - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - function abc() {new RegExp('sup')} - `, - output: ` - function abc() {/sup/} - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - function abc() {return new RegExp('sup')} - `, - output: ` - function abc() {return /sup/} - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc <<= new RegExp('cba'); - `, - output: ` - abc <<= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc >>= new RegExp('cba'); - `, - output: ` - abc >>= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc >>>= new RegExp('cba'); - `, - output: ` - abc >>>= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc ^= new RegExp('cba'); - `, - output: ` - abc ^= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc &= new RegExp('cba'); - `, - output: ` - abc &= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc |= new RegExp('cba'); - `, - output: ` - abc |= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc ??= new RegExp('cba'); - `, - output: ` - abc ??= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc &&= new RegExp('cba'); - `, - output: ` - abc &&= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc ||= new RegExp('cba'); - `, - output: ` - abc ||= /cba/; - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc **= new RegExp('blah') - `, - output: ` - abc **= /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc /= new RegExp('blah') - `, - output: ` - abc /= /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc += new RegExp('blah') - `, - output: ` - abc += /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc -= new RegExp('blah') - `, - output: ` - abc -= /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - abc %= new RegExp('blah') - `, - output: ` - abc %= /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - () => new RegExp('blah') - `, - output: ` - () => /blah/ - `, - parserOptions: { ecmaVersion: 2021 }, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "a in /abc/" + } + ] + } + ] + }, + { + code: "\n /abc/ == new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ == /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ === new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ === /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ != new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ != /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ !== new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ !== /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ > new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ > /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ < new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ < /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ >= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ >= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ <= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ <= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ << new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ << /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ >> new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ >> /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ >>> new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ >>> /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ ^ new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ ^ /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ & new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ & /cba/;\n " + } + ] + } + ] + }, + { + code: "\n /abc/ | new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n /abc/ | /cba/;\n " + } + ] + } + ] + }, + { + code: "\n null ?? new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n null ?? /blah/\n " + } + ] + } + ] + }, + { + code: "\n abc *= new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc *= /blah/\n " + } + ] + } + ] + }, + { + code: "\n console.log({a: new RegExp('sup')})\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n console.log({a: /sup/})\n " + } + ] + } + ] + }, + { + code: "\n console.log(() => {new RegExp('sup')})\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n console.log(() => {/sup/})\n " + } + ] + } + ] + }, + { + code: "\n function abc() {new RegExp('sup')}\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n function abc() {/sup/}\n " + } + ] + } + ] + }, + { + code: "\n function abc() {return new RegExp('sup')}\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n function abc() {return /sup/}\n " + } + ] + } + ] + }, + { + code: "\n abc <<= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc <<= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc >>= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc >>= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc >>>= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc >>>= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc ^= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc ^= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc &= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc &= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc |= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc |= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc ??= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc ??= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc &&= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc &&= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc ||= new RegExp('cba');\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc ||= /cba/;\n " + } + ] + } + ] + }, + { + code: "\n abc **= new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc **= /blah/\n " + } + ] + } + ] + }, + { + code: "\n abc /= new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc /= /blah/\n " + } + ] + } + ] + }, + { + code: "\n abc += new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc += /blah/\n " + } + ] + } + ] + }, + { + code: "\n abc -= new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc -= /blah/\n " + } + ] + } + ] + }, + { + code: "\n abc %= new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n abc %= /blah/\n " + } + ] + } + ] + }, + { + code: "\n () => new RegExp('blah')\n ", + output: null, + parserOptions: { + ecmaVersion: 2021 + }, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n () => /blah/\n " + } + ] + } + ] }, { code: "a/RegExp(\"foo\")in b", - output: "a/ /foo/ in b", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "a/ /foo/ in b" + } + ] + } + ] }, { code: "a/RegExp(\"foo\")instanceof b", - output: "a/ /foo/ instanceof b", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "a/ /foo/ instanceof b" + } + ] + } + ] }, { code: "do RegExp(\"foo\")\nwhile (true);", - output: "do /foo/\nwhile (true);", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "do /foo/\nwhile (true);" + } + ] + } + ] }, { code: "for(let i;i<5;i++) { break\nnew RegExp('search')}", - output: "for(let i;i<5;i++) { break\n/search/}", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "for(let i;i<5;i++) { break\n/search/}" + } + ] + } + ] }, { code: "for(let i;i<5;i++) { continue\nnew RegExp('search')}", - output: "for(let i;i<5;i++) { continue\n/search/}", - errors: [{ messageId: "unexpectedRegExp" }] - }, - { - code: ` - switch (value) { - case "possibility": - console.log('possibility matched') - case RegExp('myReg').toString(): - console.log('matches a regexp\\' toString value') - break; - } - `, - output: ` - switch (value) { - case "possibility": - console.log('possibility matched') - case /myReg/.toString(): - console.log('matches a regexp\\' toString value') - break; - } - `, - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "for(let i;i<5;i++) { continue\n/search/}" + } + ] + } + ] + }, + { + code: "\n switch (value) {\n case \"possibility\":\n console.log('possibility matched')\n case RegExp('myReg').toString():\n console.log('matches a regexp\\' toString value')\n break;\n }\n ", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "\n switch (value) {\n case \"possibility\":\n console.log('possibility matched')\n case /myReg/.toString():\n console.log('matches a regexp\\' toString value')\n break;\n }\n " + } + ] + } + ] }, { code: "throw new RegExp('abcdefg') // fail with a regular expression", - output: "throw /abcdefg/ // fail with a regular expression", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "throw /abcdefg/ // fail with a regular expression" + } + ] + } + ] }, { code: "for (value of new RegExp('something being searched')) { console.log(value) }", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()", output: null, - parserOptions: { ecmaVersion: 2018 }, - errors: [{ messageId: "unexpectedRegExp" }] + parserOptions: { + ecmaVersion: 2018 + }, + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "for (value in new RegExp('something being searched')) { console.log(value) }", - output: "for (value in /something being searched/) { console.log(value) }", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "for (value in /something being searched/) { console.log(value) }" + } + ] + } + ] }, { code: "if (condition1 && condition2) new RegExp('avalue').test(str);", output: null, - errors: [{ messageId: "unexpectedRegExp" }] + errors: [ + { + messageId: "unexpectedRegExp" + } + ] }, { code: "debugger\nnew RegExp('myReg')", - output: "debugger\n/myReg/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "debugger\n/myReg/" + } + ] + } + ] }, { code: "RegExp(\"\\\\\\n\")", - output: "/\\n/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n/" + } + ] + } + ] }, { code: "RegExp(\"\\\\\\t\")", - output: "/\\t/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\t/" + } + ] + } + ] }, { code: "RegExp(\"\\\\\\f\")", - output: "/\\f/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\f/" + } + ] + } + ] }, { code: "RegExp(\"\\\\\\v\")", - output: "/\\v/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\v/" + } + ] + } + ] }, { code: "RegExp(\"\\\\\\r\")", - output: "/\\r/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\r/" + } + ] + } + ] }, { code: "new RegExp(\"\t\")", - output: "/\\t/", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\t/" + } + ] + } + ] }, { code: "new RegExp(\"/\")", - output: "/\\//", - errors: [{ messageId: "unexpectedRegExp" }] + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\//" + } + ] + } + ] } ] }); From 6cbcf4b4bd65194c03592b5b2d071e9ecaa98797 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sat, 25 Sep 2021 15:13:08 -0700 Subject: [PATCH 11/27] New: More test cases for . --- tests/lib/rules/prefer-regex-literals.js | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index aa30726ecf1..6cbbb30b30b 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -2408,6 +2408,36 @@ ruleTester.run("prefer-regex-literals", rule, { ] } ] + }, + { + code: "new RegExp(\"\\.\")", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/./" + } + ] + } + ] + }, + { + code: "new RegExp(\"\\\\.\")", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\./" + } + ] + } + ] } ] }); From 9ae6a20ee5b19c1d6ffc14bba24f371b867d81c2 Mon Sep 17 00:00:00 2001 From: Yash Singh Date: Fri, 29 Oct 2021 20:48:56 -0700 Subject: [PATCH 12/27] Remove meta.docs.suggestion Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 683ee35ffa2..7498b2d875c 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -123,7 +123,6 @@ module.exports = { description: "disallow use of the `RegExp` constructor in favor of regular expression literals", recommended: false, url: "https://eslint.org/docs/rules/prefer-regex-literals", - suggestion: true }, fixable: "code", From ea60c814c1cda0dc4c1afb8a181ce7b016cfbc3c Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 29 Oct 2021 20:50:53 -0700 Subject: [PATCH 13/27] Fix linting --- lib/rules/prefer-regex-literals.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 7498b2d875c..c048f587600 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -122,7 +122,7 @@ module.exports = { docs: { description: "disallow use of the `RegExp` constructor in favor of regular expression literals", recommended: false, - url: "https://eslint.org/docs/rules/prefer-regex-literals", + url: "https://eslint.org/docs/rules/prefer-regex-literals" }, fixable: "code", @@ -186,10 +186,13 @@ module.exports = { function getStringValue(node) { if (isStringLiteral(node)) { return node.value; - // eslint-disable-next-line no-else-return -- No need for unnecessary cyclomatic complexity - } else if (isStaticTemplateLiteral(node)) { + } + + if (isStaticTemplateLiteral(node)) { return node.quasis[0].value.cooked; - } else if (isStringRawTaggedStaticTemplateLiteral(node)) { + } + + if (isStringRawTaggedStaticTemplateLiteral(node)) { return node.quasi.quasis[0].value.raw; } From 55664026beb9ae9cd8f4a7ab734237b90fb038f6 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 29 Oct 2021 20:54:21 -0700 Subject: [PATCH 14/27] Don't fix NULL --- lib/rules/prefer-regex-literals.js | 5 +--- tests/lib/rules/prefer-regex-literals.js | 32 +++--------------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index c048f587600..c55d66e7c1b 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -280,9 +280,6 @@ module.exports = { case "\f": return "\\f"; - case "\0": - return "\\0"; - case "/": return "\\/"; @@ -349,7 +346,7 @@ module.exports = { noFix = true; } - if (!/^[-a-zA-Z0-9\0\\[\](){}\s!@#$%^&*+^_=/~`.> Date: Sat, 30 Oct 2021 20:13:05 -0700 Subject: [PATCH 15/27] Remove redundant wrapping suggestions for now --- lib/rules/prefer-regex-literals.js | 17 ++--------------- tests/lib/rules/prefer-regex-literals.js | 8 ++++---- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index c55d66e7c1b..9ad0bae40e8 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -302,22 +302,9 @@ module.exports = { for (const { node } of tracker.iterateGlobalReferences(traceMap)) { if (disallowRedundantWrapping && isUnnecessarilyWrappedRegexLiteral(node)) { if (node.arguments.length === 2) { - context.report({ - node, - messageId: "unexpectedRedundantRegExpWithFlags", - - fix(fixer) { - return fixer.replaceTextRange(node.range, node.arguments[0].raw + getStringValue(node.arguments[1])); - } - }); + context.report({ node, messageId: "unexpectedRedundantRegExpWithFlags" }); } else { - context.report({ - node, - messageId: "unexpectedRedundantRegExp", - fix(fixer) { - return fixer.replaceTextRange(node.range, node.arguments[0].raw); - } - }); + context.report({ node, messageId: "unexpectedRedundantRegExp" }); } } else if (hasOnlyStaticStringArguments(node)) { let regexContent = getStringValue(node.arguments[0]); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index cd7f5e2ac4c..a3cb01bb9b4 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -561,7 +561,7 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/);", - output: "/a/;", + output: null, options: [ { disallowRedundantWrapping: true @@ -578,7 +578,7 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, 'u');", - output: "/a/u;", + output: null, options: [ { disallowRedundantWrapping: true @@ -595,7 +595,7 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, `u`);", - output: "/a/u;", + output: null, options: [ { disallowRedundantWrapping: true @@ -612,7 +612,7 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, String.raw`u`);", - output: "/a/u;", + output: null, options: [ { disallowRedundantWrapping: true From ab9f17df8bd45e37a1388729b2dc543c291042f5 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sat, 30 Oct 2021 20:15:26 -0700 Subject: [PATCH 16/27] String.raw can have problematic chars --- lib/rules/prefer-regex-literals.js | 2 +- tests/lib/rules/prefer-regex-literals.js | 32 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 9ad0bae40e8..9031393b08e 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -337,7 +337,7 @@ module.exports = { noFix = true; } - if (regexContent && !noFix && !isStringRawTaggedStaticTemplateLiteral(node.arguments[0])) { + if (regexContent && !noFix) { let charIncrease = 0; const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index a3cb01bb9b4..96552e68909 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -281,6 +281,38 @@ ruleTester.run("prefer-regex-literals", rule, { } ] }, + { + code: "new RegExp(String.raw`abc\nabc`);", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/abc\\nabc/;" + } + ] + } + ] + }, + { + code: "new RegExp(String.raw`\tabc\nabc`);", + output: null, + errors: [ + { + messageId: "unexpectedRegExp", + type: "NewExpression", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\tabc\\nabc/;" + } + ] + } + ] + }, { code: "RegExp(String.raw`abc`);", output: null, From 4132ed9e557d425d26e8a1c59aa08f0be88dc489 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sat, 30 Oct 2021 20:20:15 -0700 Subject: [PATCH 17/27] Remove fixable --- lib/rules/prefer-regex-literals.js | 1 - tests/lib/rules/prefer-regex-literals.js | 150 ----------------------- 2 files changed, 151 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 9031393b08e..5bece9c67f1 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -125,7 +125,6 @@ module.exports = { url: "https://eslint.org/docs/rules/prefer-regex-literals" }, - fixable: "code", hasSuggestions: true, schema: [ diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 96552e68909..55ebf28dc63 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -139,7 +139,6 @@ ruleTester.run("prefer-regex-literals", rule, { invalid: [ { code: "new RegExp('abc');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -155,7 +154,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('abc');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -171,7 +169,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('abc', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -187,7 +184,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('abc', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -203,7 +199,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(`abc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -219,7 +214,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(`abc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -235,7 +229,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(`abc`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -251,7 +244,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(`abc`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -267,7 +259,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`abc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -283,7 +274,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`abc\nabc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -299,7 +289,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`\tabc\nabc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -315,7 +304,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(String.raw`abc`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -331,7 +319,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`abc`, String.raw`g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -347,7 +334,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(String.raw`abc`, String.raw`g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -363,7 +349,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String['raw']`a`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -379,7 +364,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -395,7 +379,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -411,7 +394,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw``);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -427,7 +409,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('a', `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -443,7 +424,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(`a`, 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -459,7 +439,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(String.raw`a`, 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -475,7 +454,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`\\d`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -491,7 +469,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String.raw`\\\\d`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -507,7 +484,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String['raw']`\\\\d`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -523,7 +499,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(String[\"raw\"]`\\\\d`, `g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -539,7 +514,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('a', String.raw`g`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -555,7 +529,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new globalThis.RegExp('a');", - output: null, env: { es2020: true }, @@ -574,7 +547,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "globalThis.RegExp('a');", - output: null, env: { es2020: true }, @@ -593,7 +565,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/);", - output: null, options: [ { disallowRedundantWrapping: true @@ -610,7 +581,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, 'u');", - output: null, options: [ { disallowRedundantWrapping: true @@ -627,7 +597,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, `u`);", - output: null, options: [ { disallowRedundantWrapping: true @@ -644,7 +613,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(/a/, String.raw`u`);", - output: null, options: [ { disallowRedundantWrapping: true @@ -661,7 +629,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('a');", - output: null, options: [ { disallowRedundantWrapping: true @@ -684,7 +651,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp((String?.raw)`a`);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -699,7 +665,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('+');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -708,7 +673,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('*');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -717,7 +681,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('+');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -726,7 +689,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('*');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -735,7 +697,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('+', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -744,7 +705,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('*', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -753,7 +713,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('+', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -762,7 +721,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('*', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -771,7 +729,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('abc', 'u');", - output: null, parserOptions: { ecmaVersion: 3 }, @@ -783,7 +740,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('abc', 'd');", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -795,7 +751,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('abc', 'd');", - output: null, parserOptions: { ecmaVersion: 2022 }, @@ -813,7 +768,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\\\\\', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -828,7 +782,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\n', '');", - output: null, parserOptions: { ecmaVersion: 2022 }, @@ -846,7 +799,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\n\\n', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -861,7 +813,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\t', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -876,7 +827,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\t\\t', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -891,7 +841,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\r\\n', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -906,7 +855,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\u1234', 'g')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -915,7 +863,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\u{1234}', 'g')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -924,7 +871,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\u{11111}', 'g')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -933,7 +879,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\v', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -948,7 +893,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\v\\v', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -963,7 +907,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\f', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -978,7 +921,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\f\\f', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -993,7 +935,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\b', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1008,7 +949,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\b\\\\b', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1023,7 +963,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('\\\\B\\\\b', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1038,7 +977,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\w', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1053,7 +991,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new globalThis.RegExp('\\\\W', '');", - output: null, globals: { globalThis: "readonly" }, @@ -1071,7 +1008,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\s', '');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1086,7 +1022,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('\\\\S', '')", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1101,7 +1036,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "globalThis.RegExp('\\\\d', '');", - output: null, globals: { globalThis: "readonly" }, @@ -1119,7 +1053,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "globalThis.RegExp('\\\\D', '')", - output: null, globals: { globalThis: "readonly" }, @@ -1137,7 +1070,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "globalThis.RegExp('\\\\\\\\\\\\D', '')", - output: null, globals: { globalThis: "readonly" }, @@ -1155,7 +1087,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('\\\\D\\\\D', '')", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1170,7 +1101,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new globalThis.RegExp('\\\\0\\\\0', '');", - output: null, globals: { globalThis: "writable" }, @@ -1182,7 +1112,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('\\\\0\\\\0', '');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1191,7 +1120,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp('\\0\\0', 'g');", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1200,7 +1128,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\0\\\\0\\\\0', '')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1209,7 +1136,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp('\\\\78\\\\126\\\\5934', '')", - output: null, parserOptions: { ecmaVersion: 2022 }, @@ -1227,7 +1153,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');", - output: null, env: { browser: true }, @@ -1245,7 +1170,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "a in(RegExp('abc'))", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1260,7 +1184,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "x = y\n RegExp(\"foo\").test(x) ? bar() : baz()", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1269,7 +1192,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1281,7 +1203,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "x = y;\n RegExp(\"foo\").test(x) ? bar() : baz()", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1296,7 +1217,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "typeof RegExp(\"foo\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1311,7 +1231,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1326,7 +1245,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "[ new RegExp(`someregular`)]", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1341,7 +1259,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "const totallyValidatesEmails = new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")\n if (typeof totallyValidatesEmails === 'object') {\n runSomethingThatExists(Regexp('stuff'))\n }", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1356,7 +1273,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1383,7 +1299,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "#!/usr/bin/sh\n RegExp(\"foo\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1398,7 +1313,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "async function abc(){await new RegExp(\"foo\")}", - output: null, parserOptions: { ecmaVersion: 8, sourceType: "module" @@ -1411,7 +1325,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "function* abc(){yield new RegExp(\"foo\")}", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1420,7 +1333,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "function* abc(){yield* new RegExp(\"foo\")}", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1435,7 +1347,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "console.log({ ...new RegExp('a') })", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1450,7 +1361,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "delete RegExp('a');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1465,7 +1375,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "void RegExp('a');", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1480,7 +1389,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1492,7 +1400,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -1504,7 +1411,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "a in RegExp('abc')", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -1519,7 +1425,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ == new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1537,7 +1442,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ === new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1555,7 +1459,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ != new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1573,7 +1476,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ !== new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1591,7 +1493,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ > new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1609,7 +1510,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ < new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1627,7 +1527,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ >= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1645,7 +1544,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ <= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1663,7 +1561,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ << new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1681,7 +1578,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ >> new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1699,7 +1595,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ >>> new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1717,7 +1612,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ ^ new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1735,7 +1629,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ & new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1753,7 +1646,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n /abc/ | new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1771,7 +1663,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n null ?? new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1789,7 +1680,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc *= new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1807,7 +1697,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n console.log({a: new RegExp('sup')})\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1825,7 +1714,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n console.log(() => {new RegExp('sup')})\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1843,7 +1731,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n function abc() {new RegExp('sup')}\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1861,7 +1748,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n function abc() {return new RegExp('sup')}\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1879,7 +1765,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc <<= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1897,7 +1782,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc >>= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1915,7 +1799,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc >>>= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1933,7 +1816,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc ^= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1951,7 +1833,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc &= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1969,7 +1850,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc |= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -1987,7 +1867,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc ??= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2005,7 +1884,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc &&= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2023,7 +1901,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc ||= new RegExp('cba');\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2041,7 +1918,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc **= new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2059,7 +1935,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc /= new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2077,7 +1952,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc += new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2095,7 +1969,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc -= new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2113,7 +1986,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n abc %= new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2131,7 +2003,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n () => new RegExp('blah')\n ", - output: null, parserOptions: { ecmaVersion: 2021 }, @@ -2149,7 +2020,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "a/RegExp(\"foo\")in b", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2164,7 +2034,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "a/RegExp(\"foo\")instanceof b", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2179,7 +2048,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "do RegExp(\"foo\")\nwhile (true);", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2194,7 +2062,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "for(let i;i<5;i++) { break\nnew RegExp('search')}", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2209,7 +2076,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "for(let i;i<5;i++) { continue\nnew RegExp('search')}", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2224,7 +2090,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "\n switch (value) {\n case \"possibility\":\n console.log('possibility matched')\n case RegExp('myReg').toString():\n console.log('matches a regexp\\' toString value')\n break;\n }\n ", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2239,7 +2104,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "throw new RegExp('abcdefg') // fail with a regular expression", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2254,7 +2118,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "for (value of new RegExp('something being searched')) { console.log(value) }", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -2263,7 +2126,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()", - output: null, parserOptions: { ecmaVersion: 2018 }, @@ -2275,7 +2137,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "for (value in new RegExp('something being searched')) { console.log(value) }", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2290,7 +2151,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "if (condition1 && condition2) new RegExp('avalue').test(str);", - output: null, errors: [ { messageId: "unexpectedRegExp" @@ -2299,7 +2159,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "debugger\nnew RegExp('myReg')", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2314,7 +2173,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"\\\\\\n\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2329,7 +2187,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"\\\\\\t\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2344,7 +2201,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"\\\\\\f\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2359,7 +2215,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"\\\\\\v\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2374,7 +2229,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "RegExp(\"\\\\\\r\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2389,7 +2243,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"\t\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2404,7 +2257,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"/\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2419,7 +2271,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"\\.\")", - output: null, errors: [ { messageId: "unexpectedRegExp", @@ -2434,7 +2285,6 @@ ruleTester.run("prefer-regex-literals", rule, { }, { code: "new RegExp(\"\\\\.\")", - output: null, errors: [ { messageId: "unexpectedRegExp", From 9f42bdf431498d882523ed5c9d3c67cd01115003 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Sat, 30 Oct 2021 20:30:13 -0700 Subject: [PATCH 18/27] Fix messed up char increase --- lib/rules/prefer-regex-literals.js | 13 ++++------- tests/lib/rules/prefer-regex-literals.js | 28 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 5bece9c67f1..40c8e0f8553 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -343,18 +343,13 @@ module.exports = { visitRegExpAST(ast, { onCharacterEnter(characterNode) { - let changeCharIncrease = true; + let changeCharIncrease = 0; let stringCodePointValue = String.fromCodePoint(characterNode.value); const escaped = resolveEscapes(stringCodePointValue); if (escaped) { stringCodePointValue = escaped; - } else { - changeCharIncrease = false; - } - - if (characterNode.value === 0 && characterNode.raw !== "\0") { - changeCharIncrease = false; + changeCharIncrease = characterNode.raw.length !== 1 ? 0 : 1; } regexContent = @@ -362,8 +357,8 @@ module.exports = { (escaped ? stringCodePointValue : characterNode.raw) + regexContent.slice(characterNode.end + charIncrease); - if (changeCharIncrease) { - charIncrease++; + if (changeCharIncrease !== 0) { + charIncrease += changeCharIncrease; } } }); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 55ebf28dc63..596b77a36fa 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -2296,6 +2296,34 @@ ruleTester.run("prefer-regex-literals", rule, { ] } ] + }, + { + code: "new RegExp(\"\\\\\\n\\\\\\n\")", + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n\\n/" + } + ] + } + ] + }, + { + code: "new RegExp(\"\\\\\\n\\\\\\f\\\\\\n\")", + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n\\f\\n/" + } + ] + } + ] } ] }); From 8d96676ad9012c55270bb954689bfb17223f9879 Mon Sep 17 00:00:00 2001 From: Yash Singh Date: Wed, 1 Dec 2021 10:54:28 -0800 Subject: [PATCH 19/27] Apply suggestion from code review Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 40c8e0f8553..ac19017fad0 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -332,7 +332,7 @@ module.exports = { noFix = true; } - if (!/^[-a-zA-Z0-9\\[\](){}\s!@#$%^&*+^_=/~`.> Date: Thu, 2 Dec 2021 17:23:51 -0800 Subject: [PATCH 20/27] chore: use characterNode.raw instead of characterNode.value --- lib/rules/prefer-regex-literals.js | 7 ++++++- tests/lib/rules/prefer-regex-literals.js | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index ac19017fad0..4af9dbf9ae9 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -265,18 +265,23 @@ module.exports = { function resolveEscapes(character) { switch (character) { case "\n": + case "\\\n": return "\\n"; case "\r": + case "\\\r": return "\\r"; case "\t": + case "\\\t": return "\\t"; case "\v": + case "\\\v": return "\\v"; case "\f": + case "\\\f": return "\\f"; case "/": @@ -345,7 +350,7 @@ module.exports = { onCharacterEnter(characterNode) { let changeCharIncrease = 0; let stringCodePointValue = String.fromCodePoint(characterNode.value); - const escaped = resolveEscapes(stringCodePointValue); + const escaped = resolveEscapes(characterNode.raw); if (escaped) { stringCodePointValue = escaped; diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 596b77a36fa..3fa293e6e8a 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -2324,6 +2324,20 @@ ruleTester.run("prefer-regex-literals", rule, { ] } ] + }, + { + code: "new RegExp(\"\\u000A\\u000A\");", + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "unexpectedRegExp", + output: "/\\n\\n/;" + } + ] + } + ] } ] }); From d4353a389ec9e6c35a48933cb1ea8b2e5df9fef2 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Thu, 9 Dec 2021 18:55:00 -0800 Subject: [PATCH 21/27] chore: do a bit of simplification of onCharacterEnter --- lib/rules/prefer-regex-literals.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 4af9dbf9ae9..22e98affcbe 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -348,22 +348,19 @@ module.exports = { visitRegExpAST(ast, { onCharacterEnter(characterNode) { - let changeCharIncrease = 0; let stringCodePointValue = String.fromCodePoint(characterNode.value); const escaped = resolveEscapes(characterNode.raw); if (escaped) { stringCodePointValue = escaped; - changeCharIncrease = characterNode.raw.length !== 1 ? 0 : 1; - } - - regexContent = + regexContent = regexContent.slice(0, characterNode.start + charIncrease) + - (escaped ? stringCodePointValue : characterNode.raw) + + stringCodePointValue + regexContent.slice(characterNode.end + charIncrease); - if (changeCharIncrease !== 0) { - charIncrease += changeCharIncrease; + if (characterNode.raw.length === 1) { + charIncrease += 1; + } } } }); From b4355d14557a40a07238e9915a827b05983d3b3b Mon Sep 17 00:00:00 2001 From: Yash Singh Date: Fri, 10 Dec 2021 17:36:28 -0800 Subject: [PATCH 22/27] Apply suggestions from code review Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 22e98affcbe..6c068bf15a9 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -243,18 +243,16 @@ module.exports = { return false; } - /* eslint-disable jsdoc/valid-types -- eslint-plugin-jsdoc's type parser doesn't support square brackets */ /** * Returns a ecmaVersion compatible for regexpp. - * @param {import("../linter/linter").ParserOptions["ecmaVersion"]} ecmaVersion The ecmaVersion to convert. + * @param {any} ecmaVersion The ecmaVersion to convert. * @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp. */ function getRegexppEcmaVersion(ecmaVersion) { - /* eslint-enable jsdoc/valid-types -- JSDoc is over, enable jsdoc/valid-types again */ - if (!ecmaVersion || ecmaVersion > 13 || ecmaVersion === 3 || ecmaVersion === 5) { + if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) { return 5; } - return ecmaVersion + 2009; + return Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION); } /** @@ -341,6 +339,10 @@ module.exports = { noFix = true; } + if (sourceCode.getCommentsInside(node).length > 0) { + noFix = true; + } + if (regexContent && !noFix) { let charIncrease = 0; @@ -355,7 +357,7 @@ module.exports = { stringCodePointValue = escaped; regexContent = regexContent.slice(0, characterNode.start + charIncrease) + - stringCodePointValue + + escaped + regexContent.slice(characterNode.end + charIncrease); if (characterNode.raw.length === 1) { @@ -376,8 +378,8 @@ module.exports = { fix(fixer) { const tokenAfter = sourceCode.getTokenAfter(node); - return fixer.replaceTextRange( - node.range, + return fixer.replaceText( + node, (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && /\S/u.test(text[node.range[0] - 1]) ? " " : "") + newRegExpValue + (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && /\S/u.test(text[node.range[1]]) ? " " : "") From e292a7714dc5a682bf63107b08c16ef740a2e298 Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 10 Dec 2021 17:39:38 -0800 Subject: [PATCH 23/27] chore: more changes following code review --- lib/rules/prefer-regex-literals.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 6c068bf15a9..381d84911ce 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -18,6 +18,8 @@ const { canTokensBeAdjacent } = require("./utils/ast-utils"); // Helpers //------------------------------------------------------------------------------ +const REGEXPP_LATEST_ECMA_VERSION = 2022; + /** * Determines whether the given node is a string literal. * @param {ASTNode} node Node to check. @@ -342,7 +344,7 @@ module.exports = { if (sourceCode.getCommentsInside(node).length > 0) { noFix = true; } - + if (regexContent && !noFix) { let charIncrease = 0; @@ -350,11 +352,9 @@ module.exports = { visitRegExpAST(ast, { onCharacterEnter(characterNode) { - let stringCodePointValue = String.fromCodePoint(characterNode.value); const escaped = resolveEscapes(characterNode.raw); if (escaped) { - stringCodePointValue = escaped; regexContent = regexContent.slice(0, characterNode.start + charIncrease) + escaped + From d6dcde563f8e7a9111aa064c8a39579de25e2b2b Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 10 Dec 2021 17:43:36 -0800 Subject: [PATCH 24/27] chore: Use reliable way of testing if spacing needed Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 381d84911ce..b4fb1d4ee46 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -152,7 +152,6 @@ module.exports = { create(context) { const [{ disallowRedundantWrapping = false } = {}] = context.options; const sourceCode = context.getSourceCode(); - const text = sourceCode.getText(); /** * Determines whether the given identifier node is a reference to a global variable. @@ -380,9 +379,9 @@ module.exports = { return fixer.replaceText( node, - (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && /\S/u.test(text[node.range[0] - 1]) ? " " : "") + + (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && tokenBefore.range[1] === node.range[0] ? " " : "") + newRegExpValue + - (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && /\S/u.test(text[node.range[1]]) ? " " : "") + (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && node.range[1] === tokenAfter.range[0] ? " " : "") ); } }] From 300f349528bc6f160ef5b839cb2e38c47456061f Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Fri, 10 Dec 2021 17:50:21 -0800 Subject: [PATCH 25/27] diff msg for suggestion than main warning --- lib/rules/prefer-regex-literals.js | 3 +- tests/lib/rules/prefer-regex-literals.js | 242 +++++++++++------------ 2 files changed, 123 insertions(+), 122 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index b4fb1d4ee46..46a5b1fc858 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -144,6 +144,7 @@ module.exports = { messages: { unexpectedRegExp: "Use a regular expression literal instead of the 'RegExp' constructor.", + replaceWithLiteral: "Replace with an equivalent regular expression literal.", unexpectedRedundantRegExp: "Regular expression literal is unnecessarily wrapped within a 'RegExp' constructor.", unexpectedRedundantRegExpWithFlags: "Use regular expression literal with flags instead of the 'RegExp' constructor." } @@ -373,7 +374,7 @@ module.exports = { node, messageId: "unexpectedRegExp", suggest: noFix ? [] : [{ - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", fix(fixer) { const tokenAfter = sourceCode.getTokenAfter(node); diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 3fa293e6e8a..81cd51a52d0 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -145,7 +145,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -160,7 +160,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -175,7 +175,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -190,7 +190,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -205,7 +205,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -220,7 +220,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -235,7 +235,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -250,7 +250,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -265,7 +265,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -280,7 +280,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc\\nabc/;" } ] @@ -295,7 +295,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\tabc\\nabc/;" } ] @@ -310,7 +310,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/;" } ] @@ -325,7 +325,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -340,7 +340,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/g;" } ] @@ -355,7 +355,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/;" } ] @@ -370,7 +370,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/(?:)/;" } ] @@ -385,7 +385,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/(?:)/;" } ] @@ -400,7 +400,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/(?:)/;" } ] @@ -415,7 +415,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/g;" } ] @@ -430,7 +430,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/g;" } ] @@ -445,7 +445,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/g;" } ] @@ -460,7 +460,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\d/g;" } ] @@ -475,7 +475,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\\\d/g;" } ] @@ -490,7 +490,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\\\d/g;" } ] @@ -505,7 +505,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\\\d/g;" } ] @@ -520,7 +520,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/g;" } ] @@ -538,7 +538,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "NewExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/;" } ] @@ -556,7 +556,7 @@ ruleTester.run("prefer-regex-literals", rule, { type: "CallExpression", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/;" } ] @@ -642,7 +642,7 @@ ruleTester.run("prefer-regex-literals", rule, { column: 1, suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/;" } ] @@ -656,7 +656,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/a/;" } ] @@ -759,7 +759,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/abc/d;" } ] @@ -773,7 +773,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\\\/;" } ] @@ -790,7 +790,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n/;" } ] @@ -804,7 +804,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n\\n/;" } ] @@ -818,7 +818,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\t/;" } ] @@ -832,7 +832,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\t\\t/;" } ] @@ -846,7 +846,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\r\\n/;" } ] @@ -884,7 +884,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\v/;" } ] @@ -898,7 +898,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\v\\v/;" } ] @@ -912,7 +912,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\f/;" } ] @@ -926,7 +926,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\f\\f/;" } ] @@ -940,7 +940,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\b/;" } ] @@ -954,7 +954,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\b\\b/;" } ] @@ -968,7 +968,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\B\\b/;" } ] @@ -982,7 +982,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\w/;" } ] @@ -999,7 +999,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\W/;" } ] @@ -1013,7 +1013,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\s/;" } ] @@ -1027,7 +1027,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\S/" } ] @@ -1044,7 +1044,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\d/;" } ] @@ -1061,7 +1061,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\D/" } ] @@ -1078,7 +1078,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\\\\\D/" } ] @@ -1092,7 +1092,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\D\\D/" } ] @@ -1144,7 +1144,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\78\\126\\5934/" } ] @@ -1161,7 +1161,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\x56\\x78\\x45/;" } ] @@ -1175,7 +1175,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "a in(/abc/)" } ] @@ -1208,7 +1208,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "x = y;\n /foo/.test(x) ? bar() : baz()" } ] @@ -1222,7 +1222,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "typeof /foo/" } ] @@ -1250,7 +1250,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "[ /someregular/]" } ] @@ -1264,7 +1264,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "const totallyValidatesEmails = /\\S+@(\\S+\\.)+\\S+/\n if (typeof totallyValidatesEmails === 'object') {\n runSomethingThatExists(Regexp('stuff'))\n }" } ] @@ -1304,7 +1304,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "#!/usr/bin/sh\n /foo/" } ] @@ -1338,7 +1338,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "function* abc(){yield* /foo/}" } ] @@ -1352,7 +1352,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "console.log({ .../a/ })" } ] @@ -1366,7 +1366,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "delete /a/;" } ] @@ -1380,7 +1380,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "void /a/;" } ] @@ -1416,7 +1416,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "a in /abc/" } ] @@ -1433,7 +1433,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ == /cba/;\n " } ] @@ -1450,7 +1450,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ === /cba/;\n " } ] @@ -1467,7 +1467,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ != /cba/;\n " } ] @@ -1484,7 +1484,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ !== /cba/;\n " } ] @@ -1501,7 +1501,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ > /cba/;\n " } ] @@ -1518,7 +1518,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ < /cba/;\n " } ] @@ -1535,7 +1535,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ >= /cba/;\n " } ] @@ -1552,7 +1552,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ <= /cba/;\n " } ] @@ -1569,7 +1569,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ << /cba/;\n " } ] @@ -1586,7 +1586,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ >> /cba/;\n " } ] @@ -1603,7 +1603,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ >>> /cba/;\n " } ] @@ -1620,7 +1620,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ ^ /cba/;\n " } ] @@ -1637,7 +1637,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ & /cba/;\n " } ] @@ -1654,7 +1654,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n /abc/ | /cba/;\n " } ] @@ -1671,7 +1671,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n null ?? /blah/\n " } ] @@ -1688,7 +1688,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc *= /blah/\n " } ] @@ -1705,7 +1705,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n console.log({a: /sup/})\n " } ] @@ -1722,7 +1722,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n console.log(() => {/sup/})\n " } ] @@ -1739,7 +1739,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n function abc() {/sup/}\n " } ] @@ -1756,7 +1756,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n function abc() {return /sup/}\n " } ] @@ -1773,7 +1773,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc <<= /cba/;\n " } ] @@ -1790,7 +1790,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc >>= /cba/;\n " } ] @@ -1807,7 +1807,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc >>>= /cba/;\n " } ] @@ -1824,7 +1824,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc ^= /cba/;\n " } ] @@ -1841,7 +1841,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc &= /cba/;\n " } ] @@ -1858,7 +1858,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc |= /cba/;\n " } ] @@ -1875,7 +1875,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc ??= /cba/;\n " } ] @@ -1892,7 +1892,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc &&= /cba/;\n " } ] @@ -1909,7 +1909,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc ||= /cba/;\n " } ] @@ -1926,7 +1926,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc **= /blah/\n " } ] @@ -1943,7 +1943,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc /= /blah/\n " } ] @@ -1960,7 +1960,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc += /blah/\n " } ] @@ -1977,7 +1977,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc -= /blah/\n " } ] @@ -1994,7 +1994,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n abc %= /blah/\n " } ] @@ -2011,7 +2011,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n () => /blah/\n " } ] @@ -2025,7 +2025,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "a/ /foo/ in b" } ] @@ -2039,7 +2039,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "a/ /foo/ instanceof b" } ] @@ -2053,7 +2053,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "do /foo/\nwhile (true);" } ] @@ -2067,7 +2067,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "for(let i;i<5;i++) { break\n/search/}" } ] @@ -2081,7 +2081,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "for(let i;i<5;i++) { continue\n/search/}" } ] @@ -2095,7 +2095,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "\n switch (value) {\n case \"possibility\":\n console.log('possibility matched')\n case /myReg/.toString():\n console.log('matches a regexp\\' toString value')\n break;\n }\n " } ] @@ -2109,7 +2109,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "throw /abcdefg/ // fail with a regular expression" } ] @@ -2142,7 +2142,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "for (value in /something being searched/) { console.log(value) }" } ] @@ -2164,7 +2164,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "debugger\n/myReg/" } ] @@ -2178,7 +2178,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n/" } ] @@ -2192,7 +2192,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\t/" } ] @@ -2206,7 +2206,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\f/" } ] @@ -2220,7 +2220,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\v/" } ] @@ -2234,7 +2234,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\r/" } ] @@ -2248,7 +2248,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\t/" } ] @@ -2262,7 +2262,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\//" } ] @@ -2276,7 +2276,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/./" } ] @@ -2290,7 +2290,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\./" } ] @@ -2304,7 +2304,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n\\n/" } ] @@ -2318,7 +2318,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n\\f\\n/" } ] @@ -2332,7 +2332,7 @@ ruleTester.run("prefer-regex-literals", rule, { messageId: "unexpectedRegExp", suggestions: [ { - messageId: "unexpectedRegExp", + messageId: "replaceWithLiteral", output: "/\\n\\n/;" } ] From 4fbf577ed8ee23f4190d6d2776d713662b7a3b1a Mon Sep 17 00:00:00 2001 From: Yash-Singh1 Date: Mon, 13 Dec 2021 18:33:54 -0800 Subject: [PATCH 26/27] chore: stricter testing --- lib/rules/prefer-regex-literals.js | 8 + tests/lib/rules/prefer-regex-literals.js | 196 ++++++++++++++++++----- 2 files changed, 165 insertions(+), 39 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index 46a5b1fc858..e5a670655b7 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -352,6 +352,14 @@ module.exports = { visitRegExpAST(ast, { onCharacterEnter(characterNode) { + if (noFix) { + return; + } + + if (characterNode.value === 0) { + noFix = true; + } + const escaped = resolveEscapes(characterNode.raw); if (escaped) { diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index 81cd51a52d0..a19f9afdd20 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -667,7 +667,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('+');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -675,7 +676,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('*');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -683,7 +685,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('+');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -691,7 +694,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('*');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -699,7 +703,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('+', 'g');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -707,7 +712,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('*', 'g');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -715,7 +721,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('+', 'g');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -723,7 +730,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('*', 'g');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -734,7 +742,8 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -745,7 +754,8 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -857,7 +867,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('\\u1234', 'g')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -865,7 +876,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('\\u{1234}', 'g')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -873,7 +885,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('\\u{11111}', 'g')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1106,7 +1119,8 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1114,7 +1128,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('\\\\0\\\\0', '');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1122,7 +1137,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp('\\0\\0', 'g');", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1130,7 +1146,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp('\\\\0\\\\0\\\\0', '')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1186,7 +1203,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "x = y\n RegExp(\"foo\").test(x) ? bar() : baz()", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1194,10 +1212,12 @@ ruleTester.run("prefer-regex-literals", rule, { code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1233,13 +1253,31 @@ ruleTester.run("prefer-regex-literals", rule, { code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/foo/ instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "RegExp(\"foo\") instanceof /blahblah/g ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof /(\\p{Emoji_Presentation})\\1/ug : false" + } + ] } ] }, @@ -1275,25 +1313,67 @@ ruleTester.run("prefer-regex-literals", rule, { code: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!/^Hey, /u && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && /jk$/ && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~/^Sup, / || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || /hi/ + new RegExp('person') === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + /person/ === -new RegExp('hi again') ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -/hi again/ ? 5 * new RegExp('abc') : 'notregbutstring'" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "!new RegExp('^Hey, ', 'u') && new RegExp('jk$') && ~new RegExp('^Sup, ') || new RegExp('hi') + new RegExp('person') === -new RegExp('hi again') ? 5 * /abc/ : 'notregbutstring'" + } + ] } ] }, @@ -1319,7 +1399,8 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1327,7 +1408,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "function* abc(){yield new RegExp(\"foo\")}", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -1391,10 +1473,22 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/\\S+@(\\S+\\.)+\\S+/**RegExp('a')" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**/a/" + } + ] } ] }, @@ -1402,10 +1496,22 @@ ruleTester.run("prefer-regex-literals", rule, { code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/\\S+@(\\S+\\.)+\\S+/%RegExp('a')" + } + ] }, { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%/a/" + } + ] } ] }, @@ -2120,7 +2226,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "for (value of new RegExp('something being searched')) { console.log(value) }", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -2131,7 +2238,8 @@ ruleTester.run("prefer-regex-literals", rule, { }, errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -2153,7 +2261,8 @@ ruleTester.run("prefer-regex-literals", rule, { code: "if (condition1 && condition2) new RegExp('avalue').test(str);", errors: [ { - messageId: "unexpectedRegExp" + messageId: "unexpectedRegExp", + suggestions: null } ] }, @@ -2338,6 +2447,15 @@ ruleTester.run("prefer-regex-literals", rule, { ] } ] + }, + { + code: "new RegExp('mysafereg' /* comment explaining its safety */)", + errors: [ + { + messageId: "unexpectedRegExp", + suggestions: null + } + ] } ] }); From 61bab7d3f22741e4036f6947a962fb6247d114ec Mon Sep 17 00:00:00 2001 From: Yash Singh Date: Thu, 16 Dec 2021 19:03:49 -0800 Subject: [PATCH 27/27] Apply suggestions from code review Co-authored-by: Milos Djermanovic --- lib/rules/prefer-regex-literals.js | 8 -------- tests/lib/rules/prefer-regex-literals.js | 21 ++++++++++++++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js index e5a670655b7..46a5b1fc858 100644 --- a/lib/rules/prefer-regex-literals.js +++ b/lib/rules/prefer-regex-literals.js @@ -352,14 +352,6 @@ module.exports = { visitRegExpAST(ast, { onCharacterEnter(characterNode) { - if (noFix) { - return; - } - - if (characterNode.value === 0) { - noFix = true; - } - const escaped = resolveEscapes(characterNode.raw); if (escaped) { diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js index a19f9afdd20..f2982cbfb72 100644 --- a/tests/lib/rules/prefer-regex-literals.js +++ b/tests/lib/rules/prefer-regex-literals.js @@ -1120,7 +1120,12 @@ ruleTester.run("prefer-regex-literals", rule, { errors: [ { messageId: "unexpectedRegExp", - suggestions: null + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/\\0\\0/;" + } + ] } ] }, @@ -1129,7 +1134,12 @@ ruleTester.run("prefer-regex-literals", rule, { errors: [ { messageId: "unexpectedRegExp", - suggestions: null + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/\\0\\0/;" + } + ] } ] }, @@ -1147,7 +1157,12 @@ ruleTester.run("prefer-regex-literals", rule, { errors: [ { messageId: "unexpectedRegExp", - suggestions: null + suggestions: [ + { + messageId: "replaceWithLiteral", + output: "/\\0\\0\\0/" + } + ] } ] },