Repository: eslint/eslint
Pull request #15230 (2021-10-29 00:29:06)

fix: improve fixer of `prefer-template` rule
<!--
    Thank you for contributing!

    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

#### Prerequisites checklist

- [x] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/HEAD/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

<!--
    The following template is intentionally not a markdown checkbox list for the reasons
    explained in https://github.com/eslint/eslint/pull/12848#issuecomment-580302888
-->

[ ] Documentation update
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-change-proposal.md))
[ ] Add auto fixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

#### What changes did you make? (Give an overview)

Resolve https://github.com/eslint/eslint/issues/15083

**Before**

code: `var foo = "Hello " + "world " + test` => fixed code: var foo = `${"Hello " + "world "}${test}`

**After**

code: `var foo = "Hello " + "world " + test `=> fixed code: var foo = ``Hello world ${  test}``

#### Is there anything you'd like reviewers to focus on?
No


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1087ab4e4..5d9aa9536 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,9 +31,9 @@ jobs:
         node: [17.x, 16.x, 14.x, 12.x, "12.22.0"]
         include:
         - os: windows-latest
-          node: "12.x"
+          node: "16.x"
         - os: macOS-latest
-          node: "12.x"
+          node: "16.x"
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3b7859913..d1190eb26 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+v8.4.1 - December 6, 2021
+
+* [`234e3d9`](https://github.com/eslint/eslint/commit/234e3d98eeab8956cefb14c982b9c348c21bb2d9) fix: revert changes to reported locations in max-lines-per-function (#15397) (Milos Djermanovic)
+* [`fa4d483`](https://github.com/eslint/eslint/commit/fa4d4830a0e77f92154079ada17ffb893ce64232) docs: fix typo in example for `sort-keys` rule (#15393) (Nitin Kumar)
+
 v8.4.0 - December 3, 2021
 
 * [`efede90`](https://github.com/eslint/eslint/commit/efede90d59edc5cca9cd739df7e98f1ff00ca37d) chore: upgrade @eslint/eslintrc@1.0.5 (#15389) (Milos Djermanovic)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8f2246f3b..40163d868 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,7 +19,7 @@ To report a security vulnerability in ESLint, please use our [HackerOne program]
 
 ## Contributing Code
 
-Please sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint) and read over the [Pull Request Guidelines](https://eslint.org/docs/developer-guide/contributing/pull-requests).
+In order to submit code or documentation to an ESLint project, you’ll be asked to sign our CLA when you send your first pull request. (Read more about the Open JS Foundation CLA process at <https://cla.openjsf.org/>.) Also, please read over the [Pull Request Guidelines](https://eslint.org/docs/developer-guide/contributing/pull-requests).
 
 ## Full Documentation
 
diff --git a/docs/rules/array-element-newline.md b/docs/rules/array-element-newline.md
index cee739d74..650a00892 100644
--- a/docs/rules/array-element-newline.md
+++ b/docs/rules/array-element-newline.md
@@ -42,7 +42,12 @@ Examples of **incorrect** code for this rule with the default `"always"` option:
 
 var c = [1, 2];
 var d = [1, 2, 3];
-var e = [
+var e = [1, 2, 3
+];
+var f = [
+  1, 2, 3
+];
+var g = [
     function foo() {
         dosomething();
     }, function bar() {
@@ -63,6 +68,11 @@ var c = [1,
 var d = [1,
     2,
     3];
+var d = [
+  1, 
+  2, 
+  3
+];
 var e = [
     function foo() {
         dosomething();
@@ -109,6 +119,11 @@ var b = [1];
 var c = [1, 2];
 var d = [1, 2, 3];
 var e = [
+    1, 2, 3];
+var f = [
+  1, 2, 3
+];
+var g = [
     function foo() {
         dosomething();
     }, function bar() {
diff --git a/docs/rules/class-methods-use-this.md b/docs/rules/class-methods-use-this.md
index 7e25b069a..518a891d3 100644
--- a/docs/rules/class-methods-use-this.md
+++ b/docs/rules/class-methods-use-this.md
@@ -129,7 +129,7 @@ class A {
 }
 ```
 
-## enforceForClassFields
+### enforceForClassFields
 
 ```js
 "class-methods-use-this": [<enabled>, { "enforceForClassFields": true | false }]
diff --git a/docs/rules/computed-property-spacing.md b/docs/rules/computed-property-spacing.md
index 3fdd70ce0..903642391 100644
--- a/docs/rules/computed-property-spacing.md
+++ b/docs/rules/computed-property-spacing.md
@@ -48,6 +48,9 @@ obj[foo ]
 obj[ 'foo']
 var x = {[ b ]: a}
 obj[foo[ bar ]]
+
+const { [ a ]: someProp } = obj;
+({ [ b ]: anotherProp } = anotherObj);
 ```
 
 Examples of **correct** code for this rule with the default `"never"` option:
@@ -60,6 +63,9 @@ obj[foo]
 obj['foo']
 var x = {[b]: a}
 obj[foo[bar]]
+
+const { [a]: someProp } = obj;
+({ [b]: anotherProp } = anotherObj);
 ```
 
 ### always
@@ -76,6 +82,8 @@ obj[ foo]
 obj['foo' ]
 obj[foo[ bar ]]
 var x = {[ b]: a}
+const { [a]: someProp } = obj;
+({ [b ]: anotherProp } = anotherObj);
 ```
 
 Examples of **correct** code for this rule with the `"always"` option:
@@ -88,6 +96,8 @@ obj[ foo ]
 obj[ 'foo' ]
 var x = {[ b ]: a}
 obj[ foo[ bar ] ]
+const { [ a ]: someProp } = obj;
+({ [ b ]: anotherProp } = anotherObj);
 ```
 
 #### enforceForClassMembers
diff --git a/docs/rules/for-direction.md b/docs/rules/for-direction.md
index be24f7f73..ecacabc2c 100644
--- a/docs/rules/for-direction.md
+++ b/docs/rules/for-direction.md
@@ -13,6 +13,9 @@ for (var i = 0; i < 10; i--) {
 
 for (var i = 10; i >= 0; i++) {
 }
+
+for (var i = 0; i > 10; i++) {
+}
 ```
 
 Examples of **correct** code for this rule:
diff --git a/docs/rules/prefer-object-has-own.md b/docs/rules/prefer-object-has-own.md
new file mode 100644
index 000000000..4c90078c0
--- /dev/null
+++ b/docs/rules/prefer-object-has-own.md
@@ -0,0 +1,53 @@
+# Prefer `Object.hasOwn()` over `Object.prototype.hasOwnProperty.call()` (prefer-object-has-own)
+
+It is very common to write code like:
+
+```js
+if (Object.prototype.hasOwnProperty.call(object, "foo")) {
+  console.log("has property foo");
+}
+```
+
+This is a common practice because methods on `Object.prototype` can sometimes be unavailable or redefined (see the [no-prototype-builtins](no-prototype-builtins.md) rule).
+
+Introduced in ES2022, `Object.hasOwn()` is a shorter alternative to `Object.prototype.hasOwnProperty.call()`:
+
+```js
+if (Object.hasOwn(object, "foo")) {
+  console.log("has property foo")
+}
+```
+
+## Rule Details
+
+Examples of **incorrect** code for this rule:
+
+```js
+/*eslint prefer-object-has-own: "error"*/
+
+Object.prototype.hasOwnProperty.call(obj, "a");
+
+Object.hasOwnProperty.call(obj, "a");
+
+({}).hasOwnProperty.call(obj, "a");
+
+const hasProperty = Object.prototype.hasOwnProperty.call(object, property);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+/*eslint prefer-object-has-own: "error"*/
+
+Object.hasOwn(obj, "a");
+
+const hasProperty = Object.hasOwn(object, property);
+```
+
+## When Not To Use It
+
+This rule should not be used unless ES2022 is supported in your codebase.
+
+## Further Reading
+
+* [Object.hasOwn()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn)
diff --git a/docs/rules/sort-keys.md b/docs/rules/sort-keys.md
index 937a7da81..bf4813ec4 100644
--- a/docs/rules/sort-keys.md
+++ b/docs/rules/sort-keys.md
@@ -197,7 +197,7 @@ let obj = {
 Examples of **correct** code for the `{minKeys: 4}` option:
 
 ```js
-/*eslint sort-keys: ["error", "asc", {minKeys: 4}]*//
+/*eslint sort-keys: ["error", "asc", {minKeys: 4}]*/
 /*eslint-env es6*/
 
 // 3 keys
diff --git a/lib/rules/id-match.js b/lib/rules/id-match.js
index bcc07a8e3..15908da8c 100644
--- a/lib/rules/id-match.js
+++ b/lib/rules/id-match.js
@@ -67,6 +67,8 @@ module.exports = {
             onlyDeclarations = !!options.onlyDeclarations,
             ignoreDestructuring = !!options.ignoreDestructuring;
 
+        let globalScope;
+
         //--------------------------------------------------------------------------
         // Helpers
         //--------------------------------------------------------------------------
@@ -77,6 +79,19 @@ module.exports = {
         const DECLARATION_TYPES = new Set(["FunctionDeclaration", "VariableDeclarator"]);
         const IMPORT_TYPES = new Set(["ImportSpecifier", "ImportNamespaceSpecifier", "ImportDefaultSpecifier"]);
 
+        /**
+         * Checks whether the given node represents a reference to a global variable that is not declared in the source code.
+         * These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
+         * @param {ASTNode} node `Identifier` node to check.
+         * @returns {boolean} `true` if the node is a reference to a global variable.
+         */
+        function isReferenceToGlobalVariable(node) {
+            const variable = globalScope.set.get(node.name);
+
+            return variable && variable.defs.length === 0 &&
+                variable.references.some(ref => ref.identifier === node);
+        }
+
         /**
          * Checks if a string matches the provided pattern
          * @param {string} name The string to check.
@@ -155,11 +170,19 @@ module.exports = {
 
         return {
 
+            Program() {
+                globalScope = context.getScope();
+            },
+
             Identifier(node) {
                 const name = node.name,
                     parent = node.parent,
                     effectiveParent = (parent.type === "MemberExpression") ? parent.parent : parent;
 
+                if (isReferenceToGlobalVariable(node)) {
+                    return;
+                }
+
                 if (parent.type === "MemberExpression") {
 
                     if (!checkProperties) {
diff --git a/lib/rules/index.js b/lib/rules/index.js
index ed322a412..130b635c9 100644
--- a/lib/rules/index.js
+++ b/lib/rules/index.js
@@ -255,6 +255,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
     "prefer-exponentiation-operator": () => require("./prefer-exponentiation-operator"),
     "prefer-named-capture-group": () => require("./prefer-named-capture-group"),
     "prefer-numeric-literals": () => require("./prefer-numeric-literals"),
+    "prefer-object-has-own": () => require("./prefer-object-has-own"),
     "prefer-object-spread": () => require("./prefer-object-spread"),
     "prefer-promise-reject-errors": () => require("./prefer-promise-reject-errors"),
     "prefer-reflect": () => require("./prefer-reflect"),
diff --git a/lib/rules/max-lines-per-function.js b/lib/rules/max-lines-per-function.js
index c1b945ca1..5985a739e 100644
--- a/lib/rules/max-lines-per-function.js
+++ b/lib/rules/max-lines-per-function.js
@@ -80,7 +80,7 @@ module.exports = {
             OPTIONS_OR_INTEGER_SCHEMA
         ],
         messages: {
-            exceed: "{{name}} has exceeded the limit of lines allowed by {{linesExceed}}. Maximum allowed number of lines per function is {{maxLines}}."
+            exceed: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}."
         }
     },
 
@@ -170,26 +170,18 @@ module.exports = {
                 return;
             }
             let lineCount = 0;
-            let comments = 0;
-            let blankLines = 0;
 
             for (let i = node.loc.start.line - 1; i < node.loc.end.line; ++i) {
                 const line = lines[i];
 
                 if (skipComments) {
                     if (commentLineNumbers.has(i + 1) && isFullLineComment(line, i + 1, commentLineNumbers.get(i + 1))) {
-                        if (lineCount <= maxLines) {
-                            comments++;
-                        }
                         continue;
                     }
                 }
 
                 if (skipBlankLines) {
                     if (line.match(/^\s*$/u)) {
-                        if (lineCount <= maxLines) {
-                            blankLines++;
-                        }
                         continue;
                     }
                 }
@@ -199,21 +191,11 @@ module.exports = {
 
             if (lineCount > maxLines) {
                 const name = upperCaseFirst(astUtils.getFunctionNameWithKind(funcNode));
-                const linesExceed = lineCount - maxLines;
-
-                const loc = {
-                    start: {
-                        line: node.loc.start.line + maxLines + (comments + blankLines),
-                        column: 0
-                    },
-                    end: node.loc.end
-                };
 
                 context.report({
                     node,
-                    loc,
                     messageId: "exceed",
-                    data: { name, linesExceed, maxLines }
+                    data: { name, lineCount, maxLines }
                 });
             }
         }
diff --git a/lib/rules/prefer-object-has-own.js b/lib/rules/prefer-object-has-own.js
new file mode 100644
index 000000000..19abdb315
--- /dev/null
+++ b/lib/rules/prefer-object-has-own.js
@@ -0,0 +1,112 @@
+/**
+ * @fileoverview Prefers Object.hasOwn() instead of Object.prototype.hasOwnProperty.call()
+ * @author Nitin Kumar
+ * @author Gautam Arora
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks if the given node is considered to be an access to a property of `Object.prototype`.
+ * @param {ASTNode} node `MemberExpression` node to evaluate.
+ * @returns {boolean} `true` if `node.object` is `Object`, `Object.prototype`, or `{}` (empty 'ObjectExpression' node).
+ */
+function hasLeftHandObject(node) {
+
+    /*
+     * ({}).hasOwnProperty.call(obj, prop) - `true`
+     * ({ foo }.hasOwnProperty.call(obj, prop)) - `false`, object literal should be empty
+     */
+    if (node.object.type === "ObjectExpression" && node.object.properties.length === 0) {
+        return true;
+    }
+
+    const objectNodeToCheck = node.object.type === "MemberExpression" && astUtils.getStaticPropertyName(node.object) === "prototype" ? node.object.object : node.object;
+
+    if (objectNodeToCheck.type === "Identifier" && objectNodeToCheck.name === "Object") {
+        return true;
+    }
+
+    return false;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+/** @type {import('../shared/types').Rule} */
+module.exports = {
+    meta: {
+        type: "suggestion",
+        docs: {
+            description:
+                "disallow use of `Object.prototype.hasOwnProperty.call()` and prefer use of `Object.hasOwn()`",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/prefer-object-has-own"
+        },
+        schema: [],
+        messages: {
+            useHasOwn: "Use 'Object.hasOwn()' instead of 'Object.prototype.hasOwnProperty.call()'."
+        },
+        fixable: "code"
+    },
+    create(context) {
+        return {
+            CallExpression(node) {
+                if (!(node.callee.type === "MemberExpression" && node.callee.object.type === "MemberExpression")) {
+                    return;
+                }
+
+                const calleePropertyName = astUtils.getStaticPropertyName(node.callee);
+                const objectPropertyName = astUtils.getStaticPropertyName(node.callee.object);
+                const isObject = hasLeftHandObject(node.callee.object);
+
+                // check `Object` scope
+                const scope = context.getScope();
+                const variable = astUtils.getVariableByName(scope, "Object");
+
+                if (
+                    calleePropertyName === "call" &&
+                    objectPropertyName === "hasOwnProperty" &&
+                    isObject &&
+                    variable && variable.scope.type === "global"
+                ) {
+                    context.report({
+                        node,
+                        messageId: "useHasOwn",
+                        fix(fixer) {
+                            const sourceCode = context.getSourceCode();
+
+                            if (sourceCode.getCommentsInside(node.callee).length > 0) {
+                                return null;
+                            }
+
+                            const tokenJustBeforeNode = sourceCode.getTokenBefore(node.callee, { includeComments: true });
+
+                            // for https://github.com/eslint/eslint/pull/15346#issuecomment-991417335
+                            if (
+                                tokenJustBeforeNode &&
+                                tokenJustBeforeNode.range[1] === node.callee.range[0] &&
+                                !astUtils.canTokensBeAdjacent(tokenJustBeforeNode, "Object.hasOwn")
+                            ) {
+                                return fixer.replaceText(node.callee, " Object.hasOwn");
+                            }
+
+                            return fixer.replaceText(node.callee, "Object.hasOwn");
+                        }
+                    });
+                }
+            }
+        };
+    }
+};
diff --git a/lib/rules/prefer-regex-literals.js b/lib/rules/prefer-regex-literals.js
index afd6a0139..158f84b94 100644
--- a/lib/rules/prefer-regex-literals.js
+++ b/lib/rules/prefer-regex-literals.js
@@ -11,11 +11,15 @@
 
 const astUtils = require("./utils/ast-utils");
 const { CALL, CONSTRUCT, ReferenceTracker, findVariable } = require("eslint-utils");
+const { RegExpValidator, visitRegExpAST, RegExpParser } = require("regexpp");
+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.
@@ -43,6 +47,71 @@ function isStaticTemplateLiteral(node) {
     return node.type === "TemplateLiteral" && node.expressions.length === 0;
 }
 
+const validPrecedingTokens = [
+    "(",
+    ";",
+    "[",
+    ",",
+    "=",
+    "+",
+    "*",
+    "-",
+    "?",
+    "~",
+    "%",
+    "**",
+    "!",
+    "typeof",
+    "instanceof",
+    "&&",
+    "||",
+    "??",
+    "return",
+    "...",
+    "delete",
+    "void",
+    "in",
+    "<",
+    ">",
+    "<=",
+    ">=",
+    "==",
+    "===",
+    "!=",
+    "!==",
+    "<<",
+    ">>",
+    ">>>",
+    "&",
+    "|",
+    "^",
+    ":",
+    "{",
+    "=>",
+    "*=",
+    "<<=",
+    ">>=",
+    ">>>=",
+    "^=",
+    "|=",
+    "&=",
+    "??=",
+    "||=",
+    "&&=",
+    "**=",
+    "+=",
+    "-=",
+    "/=",
+    "%=",
+    "/",
+    "do",
+    "break",
+    "continue",
+    "debugger",
+    "case",
+    "throw"
+];
+
 
 //------------------------------------------------------------------------------
 // Rule Definition
@@ -59,6 +128,8 @@ module.exports = {
             url: "https://eslint.org/docs/rules/prefer-regex-literals"
         },
 
+        hasSuggestions: true,
+
         schema: [
             {
                 type: "object",
@@ -74,6 +145,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."
         }
@@ -81,6 +153,7 @@ module.exports = {
 
     create(context) {
         const [{ disallowRedundantWrapping = false } = {}] = context.options;
+        const sourceCode = context.getSourceCode();
 
         /**
          * Determines whether the given identifier node is a reference to a global variable.
@@ -107,6 +180,27 @@ module.exports = {
                 isStaticTemplateLiteral(node.quasi);
         }
 
+        /**
+         * Gets the value of a string
+         * @param {ASTNode} node The node to get the string of.
+         * @returns {string|null} The value of the node.
+         */
+        function getStringValue(node) {
+            if (isStringLiteral(node)) {
+                return node.value;
+            }
+
+            if (isStaticTemplateLiteral(node)) {
+                return node.quasis[0].value.cooked;
+            }
+
+            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.
@@ -152,6 +246,53 @@ module.exports = {
             return false;
         }
 
+        /**
+         * Returns a ecmaVersion compatible for regexpp.
+         * @param {any} ecmaVersion The ecmaVersion to convert.
+         * @returns {import("regexpp/ecma-versions").EcmaVersion} The resulting ecmaVersion compatible for regexpp.
+         */
+        function getRegexppEcmaVersion(ecmaVersion) {
+            if (typeof ecmaVersion !== "number" || ecmaVersion <= 5) {
+                return 5;
+            }
+            return Math.min(ecmaVersion + 2009, REGEXPP_LATEST_ECMA_VERSION);
+        }
+
+        /**
+         * Makes a character escaped or else returns null.
+         * @param {string} character The character to escape.
+         * @returns {string} The resulting escaped character.
+         */
+        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 "/":
+                    return "\\/";
+
+                default:
+                    return null;
+            }
+        }
+
         return {
             Program() {
                 const scope = context.getScope();
@@ -171,7 +312,82 @@ module.exports = {
                             context.report({ node, messageId: "unexpectedRedundantRegExp" });
                         }
                     } else if (hasOnlyStaticStringArguments(node)) {
-                        context.report({ node, messageId: "unexpectedRegExp" });
+                        let regexContent = getStringValue(node.arguments[0]);
+                        let noFix = false;
+                        let flags;
+
+                        if (node.arguments[1]) {
+                            flags = getStringValue(node.arguments[1]);
+                        }
+
+                        const regexppEcmaVersion = getRegexppEcmaVersion(context.parserOptions.ecmaVersion);
+                        const RegExpValidatorInstance = new RegExpValidator({ ecmaVersion: regexppEcmaVersion });
+
+                        try {
+                            RegExpValidatorInstance.validatePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false);
+                            if (flags) {
+                                RegExpValidatorInstance.validateFlags(flags);
+                            }
+                        } catch {
+                            noFix = true;
+                        }
+
+                        const tokenBefore = sourceCode.getTokenBefore(node);
+
+                        if (tokenBefore && !validPrecedingTokens.includes(tokenBefore.value)) {
+                            noFix = true;
+                        }
+
+                        if (!/^[-a-zA-Z0-9\\[\](){} \t\r\n\v\f!@#$%^&*+^_=/~`.><?,'"|:;]*$/u.test(regexContent)) {
+                            noFix = true;
+                        }
+
+                        if (sourceCode.getCommentsInside(node).length > 0) {
+                            noFix = true;
+                        }
+
+                        if (regexContent && !noFix) {
+                            let charIncrease = 0;
+
+                            const ast = new RegExpParser({ ecmaVersion: regexppEcmaVersion }).parsePattern(regexContent, 0, regexContent.length, flags ? flags.includes("u") : false);
+
+                            visitRegExpAST(ast, {
+                                onCharacterEnter(characterNode) {
+                                    const escaped = resolveEscapes(characterNode.raw);
+
+                                    if (escaped) {
+                                        regexContent =
+                                            regexContent.slice(0, characterNode.start + charIncrease) +
+                                            escaped +
+                                            regexContent.slice(characterNode.end + charIncrease);
+
+                                        if (characterNode.raw.length === 1) {
+                                            charIncrease += 1;
+                                        }
+                                    }
+                                }
+                            });
+                        }
+
+                        const newRegExpValue = `/${regexContent || "(?:)"}/${flags || ""}`;
+
+                        context.report({
+                            node,
+                            messageId: "unexpectedRegExp",
+                            suggest: noFix ? [] : [{
+                                messageId: "replaceWithLiteral",
+                                fix(fixer) {
+                                    const tokenAfter = sourceCode.getTokenAfter(node);
+
+                                    return fixer.replaceText(
+                                        node,
+                                        (tokenBefore && !canTokensBeAdjacent(tokenBefore, newRegExpValue) && tokenBefore.range[1] === node.range[0] ? " " : "") +
+                                            newRegExpValue +
+                                            (tokenAfter && !canTokensBeAdjacent(newRegExpValue, tokenAfter) && node.range[1] === tokenAfter.range[0] ? " " : "")
+                                    );
+                                }
+                            }]
+                        });
                     }
                 }
             }
diff --git a/lib/rules/prefer-template.js b/lib/rules/prefer-template.js
index 953155d8f..e61eac1d6 100644
--- a/lib/rules/prefer-template.js
+++ b/lib/rules/prefer-template.js
@@ -188,7 +188,7 @@ module.exports = {
                 return sourceCode.getText(currentNode);
             }
 
-            if (isConcatenation(currentNode) && hasStringLiteral(currentNode) && hasNonStringLiteral(currentNode)) {
+            if (isConcatenation(currentNode) && hasStringLiteral(currentNode)) {
                 const plusSign = sourceCode.getFirstTokenBetween(currentNode.left, currentNode.right, token => token.value === "+");
                 const textBeforePlus = getTextBetween(currentNode.left, plusSign);
                 const textAfterPlus = getTextBetween(plusSign, currentNode.right);
diff --git a/package.json b/package.json
index 82cc50e84..43a7138fc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "8.4.0",
+  "version": "8.4.1",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
diff --git a/tools/rule-types.json b/tools/rule-types.json
index 4a71a8b09..85484c492 100644
--- a/tools/rule-types.json
+++ b/tools/rule-types.json
@@ -242,6 +242,7 @@
     "prefer-exponentiation-operator": "suggestion",
     "prefer-named-capture-group": "suggestion",
     "prefer-numeric-literals": "suggestion",
+    "prefer-object-has-own": "suggestion",
     "prefer-object-spread": "suggestion",
     "prefer-promise-reject-errors": "suggestion",
     "prefer-reflect": "suggestion",


Test patch:
diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js
index 7f590a5ea..fe520a58a 100644
--- a/lib/rule-tester/rule-tester.js
+++ b/lib/rule-tester/rule-tester.js
@@ -216,6 +216,9 @@ function freezeDeeply(x) {
  * @returns {string} The sanitized text.
  */
 function sanitize(text) {
+    if (typeof text !== "string") {
+        return "";
+    }
     return text.replace(
         /[\u0000-\u0009\u000b-\u001a]/gu, // eslint-disable-line no-control-regex -- Escaping controls
         c => `\\u${c.codePointAt(0).toString(16).padStart(4, "0")}`
@@ -691,6 +694,13 @@ class RuleTester {
          * @private
          */
         function testValidTemplate(item) {
+            const code = typeof item === "object" ? item.code : item;
+
+            assert.ok(typeof code === "string", "Test case must specify a string value for 'code'");
+            if (item.name) {
+                assert.ok(typeof item.name === "string", "Optional test case property 'name' must be a string");
+            }
+
             const result = runRuleForItem(item);
             const messages = result.messages;
 
@@ -731,6 +741,10 @@ class RuleTester {
          * @private
          */
         function testInvalidTemplate(item) {
+            assert.ok(typeof item.code === "string", "Test case must specify a string value for 'code'");
+            if (item.name) {
+                assert.ok(typeof item.name === "string", "Optional test case property 'name' must be a string");
+            }
             assert.ok(item.errors || item.errors === 0,
                 `Did not specify errors for an invalid test of ${ruleName}`);
 
diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js
index 5018a037b..c6383837d 100644
--- a/tests/lib/rule-tester/rule-tester.js
+++ b/tests/lib/rule-tester/rule-tester.js
@@ -2441,6 +2441,65 @@ describe("RuleTester", () => {
 
             return assertion;
         });
+
+        it('should throw if "name" property is not a string', () => {
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: [{ code: "foo", name: 123 }],
+                    invalid: [{ code: "foo" }]
+
+                });
+            }, /Optional test case property 'name' must be a string/u);
+
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: ["foo"],
+                    invalid: [{ code: "foo", name: 123 }]
+                });
+            }, /Optional test case property 'name' must be a string/u);
+        });
+
+        it('should throw if "code" property is not a string', () => {
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: [{ code: 123 }],
+                    invalid: [{ code: "foo" }]
+
+                });
+            }, /Test case must specify a string value for 'code'/u);
+
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: [123],
+                    invalid: [{ code: "foo" }]
+
+                });
+            }, /Test case must specify a string value for 'code'/u);
+
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: ["foo"],
+                    invalid: [{ code: 123 }]
+                });
+            }, /Test case must specify a string value for 'code'/u);
+        });
+
+        it('should throw if "code" property is missing', () => {
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: [{ }],
+                    invalid: [{ code: "foo" }]
+
+                });
+            }, /Test case must specify a string value for 'code'/u);
+
+            assert.throws(() => {
+                ruleTester.run("foo", require("../../fixtures/testers/rule-tester/no-var"), {
+                    valid: ["foo"],
+                    invalid: [{ }]
+                });
+            }, /Test case must specify a string value for 'code'/u);
+        });
     });
 
     // https://github.com/eslint/eslint/issues/11615
diff --git a/tests/lib/rules/computed-property-spacing.js b/tests/lib/rules/computed-property-spacing.js
index eff0c0a73..35533d9e6 100644
--- a/tests/lib/rules/computed-property-spacing.js
+++ b/tests/lib/rules/computed-property-spacing.js
@@ -265,7 +265,30 @@ ruleTester.run("computed-property-spacing", rule, {
             ].join("\n"),
             options: ["never"],
             parserOptions: { ecmaVersion: 6 }
+        },
+
+        // Destructuring Assignment
+        {
+            code: "const { [a]: someProp } = obj;",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "({ [a]: someProp } = obj);",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "const { [ a ]: someProp } = obj;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "({ [ a ]: someProp } = obj);",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
         }
+
     ],
 
     invalid: [
@@ -2062,6 +2085,66 @@ ruleTester.run("computed-property-spacing", rule, {
                 { messageId: "unexpectedSpaceAfter", data: { tokenValue: "[" } },
                 { messageId: "unexpectedSpaceBefore", data: { tokenValue: "]" } }
             ]
+        },
+
+        // Destructuring Assignment
+        {
+            code: "const { [ a]: someProp } = obj;",
+            output: "const { [a]: someProp } = obj;",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "unexpectedSpaceAfter", data: { tokenValue: "[" } }
+            ]
+        },
+        {
+            code: "const { [a ]: someProp } = obj;",
+            output: "const { [a]: someProp } = obj;",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "unexpectedSpaceBefore", data: { tokenValue: "]" } }
+            ]
+        },
+        {
+            code: "const { [ a ]: someProp } = obj;",
+            output: "const { [a]: someProp } = obj;",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "unexpectedSpaceAfter", data: { tokenValue: "[" } },
+                { messageId: "unexpectedSpaceBefore", data: { tokenValue: "]" } }
+            ]
+        },
+        {
+            code: "({ [ a ]: someProp } = obj);",
+            output: "({ [a]: someProp } = obj);",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "unexpectedSpaceAfter", data: { tokenValue: "[" } },
+                { messageId: "unexpectedSpaceBefore", data: { tokenValue: "]" } }
+            ]
+        },
+        {
+            code: "const { [a]: someProp } = obj;",
+            output: "const { [ a ]: someProp } = obj;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "missingSpaceAfter", data: { tokenValue: "[" } },
+                { messageId: "missingSpaceBefore", data: { tokenValue: "]" } }
+            ]
+        },
+        {
+            code: "({ [a]: someProp } = obj);",
+            output: "({ [ a ]: someProp } = obj);",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2022 },
+            errors: [
+                { messageId: "missingSpaceAfter", data: { tokenValue: "[" } },
+                { messageId: "missingSpaceBefore", data: { tokenValue: "]" } }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/id-match.js b/tests/lib/rules/id-match.js
index d1fad2ecb..2f48a4b2d 100644
--- a/tests/lib/rules/id-match.js
+++ b/tests/lib/rules/id-match.js
@@ -185,6 +185,19 @@ ruleTester.run("id-match", rule, {
             }]
         },
 
+        // Should not report for global references - https://github.com/eslint/eslint/issues/15395
+        {
+            code: `
+            const foo = Object.keys(bar);
+            const a = Array.from(b);
+            const bar = () => Array;
+            `,
+            options: ["^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$", {
+                properties: true
+            }],
+            parserOptions: { ecmaVersion: 2022 }
+        },
+
         // Class Methods
         {
             code: "class x { foo() {} }",
@@ -641,6 +654,76 @@ ruleTester.run("id-match", rule, {
             ]
         },
 
+        // https://github.com/eslint/eslint/issues/15395
+        {
+            code: `
+            const foo_variable = 1;
+            class MyClass {
+            }
+            let a = new MyClass();
+            let b = {id: 1};
+            let c = Object.keys(b);
+            let d = Array.from(b);
+            let e = (Object) => Object.keys(obj, prop); // not global Object
+            let f = (Array) => Array.from(obj, prop); // not global Array
+            foo.Array = 5; // not global Array
+            `,
+            options: ["^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$", {
+                properties: true
+            }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'foo_variable' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 2,
+                    column: 19
+                },
+                {
+                    message: "Identifier 'MyClass' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 3,
+                    column: 19
+                },
+
+                // let e = (Object) => Object.keys(obj, prop)
+                {
+                    message: "Identifier 'Object' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 9,
+                    column: 22
+                },
+                {
+                    message: "Identifier 'Object' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 9,
+                    column: 33
+                },
+
+                // let f =(Array) => Array.from(obj, prop);
+                {
+                    message: "Identifier 'Array' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 10,
+                    column: 22
+                },
+                {
+                    message: "Identifier 'Array' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 10,
+                    column: 32
+                },
+
+                // foo.Array = 5;
+                {
+                    message: "Identifier 'Array' does not match the pattern '^\\$?[a-z]+([A-Z0-9][a-z0-9]+)*$'.",
+                    type: "Identifier",
+                    line: 11,
+                    column: 17
+                }
+            ]
+        },
+
         // Class Methods
         {
             code: "class x { _foo() {} }",
diff --git a/tests/lib/rules/max-lines-per-function.js b/tests/lib/rules/max-lines-per-function.js
index 74acab2af..ba01206f4 100644
--- a/tests/lib/rules/max-lines-per-function.js
+++ b/tests/lib/rules/max-lines-per-function.js
@@ -199,14 +199,7 @@ if ( x === y ) {
             code: "function name() {\n}",
             options: [1],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 1, maxLines: 1 },
-                    line: 2,
-                    column: 1,
-                    endLine: 2,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 2, maxLines: 1 } }
             ]
         },
 
@@ -215,14 +208,7 @@ if ( x === y ) {
             code: "var func = function() {\n}",
             options: [1],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function", linesExceed: 1, maxLines: 1 },
-                    line: 2,
-                    column: 1,
-                    endLine: 2,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function", lineCount: 2, maxLines: 1 } }
             ]
         },
 
@@ -231,14 +217,7 @@ if ( x === y ) {
             code: "const bar = () => {\nconst x = 2 + 1;\nreturn x;\n}",
             options: [3],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Arrow function", linesExceed: 1, maxLines: 3 },
-                    line: 4,
-                    column: 1,
-                    endLine: 4,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Arrow function", lineCount: 4, maxLines: 3 } }
             ]
         },
 
@@ -247,14 +226,7 @@ if ( x === y ) {
             code: "const bar = () =>\n 2",
             options: [1],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Arrow function", linesExceed: 1, maxLines: 1 },
-                    line: 2,
-                    column: 1,
-                    endLine: 2,
-                    endColumn: 3
-                }
+                { messageId: "exceed", data: { name: "Arrow function", lineCount: 2, maxLines: 1 } }
             ]
         },
 
@@ -263,14 +235,7 @@ if ( x === y ) {
             code: `() => {${"foo\n".repeat(60)}}`,
             options: [{}],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Arrow function", linesExceed: 11, maxLines: 50 },
-                    line: 51,
-                    column: 1,
-                    endLine: 61,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Arrow function", lineCount: 61, maxLines: 50 } }
             ]
         },
 
@@ -279,14 +244,7 @@ if ( x === y ) {
             code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
             options: [{ max: 6, skipComments: false, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 1, maxLines: 6 },
-                    line: 7,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 7, maxLines: 6 } }
             ]
         },
 
@@ -295,14 +253,7 @@ if ( x === y ) {
             code: "function name() {\r\nvar x = 5;\r\n\t\r\n \r\n\r\nvar x = 2;\r\n}",
             options: [{ max: 6, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 1, maxLines: 6 },
-                    line: 7,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 7, maxLines: 6 } }
             ]
         },
 
@@ -311,14 +262,7 @@ if ( x === y ) {
             code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
             options: [{ max: 2, skipComments: true, skipBlankLines: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 2, maxLines: 2 },
-                    line: 6,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 4, maxLines: 2 } }
             ]
         },
 
@@ -327,14 +271,7 @@ if ( x === y ) {
             code: "function name() {\r\nvar x = 5;\r\n\t\r\n \r\n\r\nvar x = 2;\r\n}",
             options: [{ max: 2, skipComments: true, skipBlankLines: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 2, maxLines: 2 },
-                    line: 6,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 4, maxLines: 2 } }
             ]
         },
 
@@ -343,14 +280,7 @@ if ( x === y ) {
             code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
             options: [{ max: 6, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 1, maxLines: 6 },
-                    line: 8,
-                    column: 1,
-                    endLine: 8,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 7, maxLines: 6 } }
             ]
         },
 
@@ -359,14 +289,7 @@ if ( x === y ) {
             code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
             options: [{ max: 1, skipComments: true, skipBlankLines: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 3, maxLines: 1 },
-                    line: 2,
-                    column: 1,
-                    endLine: 8,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 4, maxLines: 1 } }
             ]
         },
 
@@ -375,14 +298,7 @@ if ( x === y ) {
             code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
             options: [{ max: 1, skipComments: false, skipBlankLines: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 4, maxLines: 1 },
-                    line: 2,
-                    column: 1,
-                    endLine: 8,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'name'", lineCount: 5, maxLines: 1 } }
             ]
         },
 
@@ -397,14 +313,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'foo'", linesExceed: 5, maxLines: 2 },
-                    line: 3,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'foo'", lineCount: 7, maxLines: 2 } }
             ]
         },
 
@@ -419,14 +328,7 @@ function
 ()`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function", linesExceed: 2, maxLines: 2 },
-                    line: 4,
-                    column: 1,
-                    endLine: 5,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function", lineCount: 4, maxLines: 2 } }
             ]
         },
 
@@ -444,14 +346,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 9, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'parent'", linesExceed: 1, maxLines: 9 },
-                    line: 10,
-                    column: 1,
-                    endLine: 10,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'parent'", lineCount: 10, maxLines: 9 } }
             ]
         },
 
@@ -469,22 +364,8 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'parent'", linesExceed: 8, maxLines: 2 },
-                    line: 3,
-                    column: 1,
-                    endLine: 10,
-                    endColumn: 2
-                },
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'nested'", linesExceed: 2, maxLines: 2 },
-                    line: 5,
-                    column: 1,
-                    endLine: 6,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function 'parent'", lineCount: 10, maxLines: 2 } },
+                { messageId: "exceed", data: { name: "Function 'nested'", lineCount: 4, maxLines: 2 } }
             ]
         },
 
@@ -499,14 +380,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Method 'method'", linesExceed: 3, maxLines: 2 },
-                    line: 4,
-                    column: 1,
-                    endLine: 6,
-                    endColumn: 6
-                }
+                { messageId: "exceed", data: { name: "Method 'method'", lineCount: 5, maxLines: 2 } }
             ]
         },
 
@@ -521,14 +395,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Static method 'foo'", linesExceed: 3, maxLines: 2 },
-                    line: 4,
-                    column: 1,
-                    endLine: 6,
-                    endColumn: 6
-                }
+                { messageId: "exceed", data: { name: "Static method 'foo'", lineCount: 5, maxLines: 2 } }
             ]
         },
 
@@ -541,16 +408,9 @@ if ( x === y ) {
         return 1
     }
 }`,
-            options: [{ max: 4, skipComments: true, skipBlankLines: false }],
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Getter 'foo'", linesExceed: 1, maxLines: 4 },
-                    line: 6,
-                    column: 1,
-                    endLine: 6,
-                    endColumn: 6
-                }
+                { messageId: "exceed", data: { name: "Getter 'foo'", lineCount: 5, maxLines: 2 } }
             ]
         },
 
@@ -565,14 +425,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Setter 'foo'", linesExceed: 3, maxLines: 2 },
-                    line: 4,
-                    column: 1,
-                    endLine: 6,
-                    endColumn: 6
-                }
+                { messageId: "exceed", data: { name: "Setter 'foo'", lineCount: 5, maxLines: 2 } }
             ]
         },
 
@@ -590,14 +443,7 @@ if ( x === y ) {
 }`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Static method", linesExceed: 6, maxLines: 2 },
-                    line: 4,
-                    column: 1,
-                    endLine: 9,
-                    endColumn: 6
-                }
+                { messageId: "exceed", data: { name: "Static method", lineCount: 8, maxLines: 2 } }
             ]
         },
 
@@ -612,14 +458,7 @@ if ( x === y ) {
 }());`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function", linesExceed: 5, maxLines: 2 },
-                    line: 3,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Function", lineCount: 7, maxLines: 2 } }
             ]
         },
 
@@ -634,28 +473,7 @@ if ( x === y ) {
 })();`,
             options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: true }],
             errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Arrow function", linesExceed: 5, maxLines: 2 },
-                    line: 3,
-                    column: 1,
-                    endLine: 7,
-                    endColumn: 2
-                }
-            ]
-        },
-        {
-            code: "\nfoo();\nbar();\nbaz();\nfunction name() {\nvar x = 5;\n/* comment 1 */\n/* comment 2 */\n\t\n \n\nvar x = 2;\n}\nquz();",
-            options: [{ max: 2, skipComments: true, skipBlankLines: true }],
-            errors: [
-                {
-                    messageId: "exceed",
-                    data: { name: "Function 'name'", linesExceed: 2, maxLines: 2 },
-                    line: 12,
-                    column: 1,
-                    endLine: 13,
-                    endColumn: 2
-                }
+                { messageId: "exceed", data: { name: "Arrow function", lineCount: 7, maxLines: 2 } }
             ]
         }
     ]
diff --git a/tests/lib/rules/prefer-object-has-own.js b/tests/lib/rules/prefer-object-has-own.js
new file mode 100644
index 000000000..d58f7f5c2
--- /dev/null
+++ b/tests/lib/rules/prefer-object-has-own.js
@@ -0,0 +1,461 @@
+/**
+ * @fileoverview Tests for prefer-object-has-own rule.
+ * @author Nitin Kumar
+ * @author Gautam Arora
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/prefer-object-has-own");
+const { RuleTester } = require("../../../lib/rule-tester");
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const parserOptions = {
+    ecmaVersion: 2022
+};
+
+const ruleTester = new RuleTester({ parserOptions });
+
+ruleTester.run("prefer-object-has-own", rule, {
+    valid: [
+        "Object",
+        "Object(obj, prop)",
+        "Object.hasOwnProperty",
+        "Object.hasOwnProperty(prop)",
+        "hasOwnProperty(obj, prop)",
+        "foo.hasOwnProperty(prop)",
+        "foo.hasOwnProperty(obj, prop)",
+        "Object.hasOwnProperty.call",
+        "foo.Object.hasOwnProperty.call(obj, prop)",
+        "foo.hasOwnProperty.call(obj, prop)",
+        "foo.call(Object.prototype.hasOwnProperty, Object.prototype.hasOwnProperty.call)",
+        "Object.foo.call(obj, prop)",
+        "Object.hasOwnProperty.foo(obj, prop)",
+        "Object.hasOwnProperty.call.foo(obj, prop)",
+        "Object[hasOwnProperty].call(obj, prop)",
+        "Object.hasOwnProperty[call](obj, prop)",
+        "class C { #hasOwnProperty; foo() { Object.#hasOwnProperty.call(obj, prop) } }",
+        "class C { #call; foo() { Object.hasOwnProperty.#call(obj, prop) } }",
+        "(Object) => Object.hasOwnProperty.call(obj, prop)", // not global Object
+        "Object.prototype",
+        "Object.prototype(obj, prop)",
+        "Object.prototype.hasOwnProperty",
+        "Object.prototype.hasOwnProperty(obj, prop)",
+        "Object.prototype.hasOwnProperty.call",
+        "foo.Object.prototype.hasOwnProperty.call(obj, prop)",
+        "foo.prototype.hasOwnProperty.call(obj, prop)",
+        "Object.foo.hasOwnProperty.call(obj, prop)",
+        "Object.prototype.foo.call(obj, prop)",
+        "Object.prototype.hasOwnProperty.foo(obj, prop)",
+        "Object.prototype.hasOwnProperty.call.foo(obj, prop)",
+        "Object.prototype.prototype.hasOwnProperty.call(a, b);",
+        "Object.hasOwnProperty.prototype.hasOwnProperty.call(a, b);",
+        "Object.prototype[hasOwnProperty].call(obj, prop)",
+        "Object.prototype.hasOwnProperty[call](obj, prop)",
+        "class C { #hasOwnProperty; foo() { Object.prototype.#hasOwnProperty.call(obj, prop) } }",
+        "class C { #call; foo() { Object.prototype.hasOwnProperty.#call(obj, prop) } }",
+        "Object[prototype].hasOwnProperty.call(obj, prop)",
+        "class C { #prototype; foo() { Object.#prototype.hasOwnProperty.call(obj, prop) } }",
+        "(Object) => Object.prototype.hasOwnProperty.call(obj, prop)", // not global Object
+        "({})",
+        "({}(obj, prop))",
+        "({}.hasOwnProperty)",
+        "({}.hasOwnProperty(prop))",
+        "({}.hasOwnProperty(obj, prop))",
+        "({}.hasOwnProperty.call)",
+        "({}).prototype.hasOwnProperty.call(a, b);",
+        "({}.foo.call(obj, prop))",
+        "({}.hasOwnProperty.foo(obj, prop))",
+        "({}[hasOwnProperty].call(obj, prop))",
+        "({}.hasOwnProperty[call](obj, prop))",
+        "({}).hasOwnProperty[call](object, property)",
+        "({})[hasOwnProperty].call(object, property)",
+        "class C { #hasOwnProperty; foo() { ({}.#hasOwnProperty.call(obj, prop)) } }",
+        "class C { #call; foo() { ({}.hasOwnProperty.#call(obj, prop)) } }",
+        "({ foo }.hasOwnProperty.call(obj, prop))", // object literal should be empty
+        "(Object) => ({}).hasOwnProperty.call(obj, prop)", // Object is shadowed, so Object.hasOwn cannot be used here
+        `
+        let obj = {};
+        Object.hasOwn(obj,"");
+        `,
+        "const hasProperty = Object.hasOwn(object, property);",
+        `/* global Object: off */
+        ({}).hasOwnProperty.call(a, b);`
+    ],
+    invalid: [
+        {
+            code: "Object.hasOwnProperty.call(obj, 'foo')",
+            output: "Object.hasOwn(obj, 'foo')",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 39
+            }]
+        },
+        {
+            code: "Object.hasOwnProperty.call(obj, property)",
+            output: "Object.hasOwn(obj, property)",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 42
+            }]
+        },
+        {
+            code: "Object.prototype.hasOwnProperty.call(obj, 'foo')",
+            output: "Object.hasOwn(obj, 'foo')",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 49
+            }]
+        },
+        {
+            code: "({}).hasOwnProperty.call(obj, 'foo')",
+            output: "Object.hasOwn(obj, 'foo')",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 37
+            }]
+        },
+
+        //  prevent autofixing if there are any comments
+        {
+            code: "Object/* comment */.prototype.hasOwnProperty.call(a, b);",
+            output: null,
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 56
+            }]
+        },
+        {
+            code: "const hasProperty = Object.prototype.hasOwnProperty.call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 75
+            }]
+        },
+        {
+            code: "const hasProperty = (( Object.prototype.hasOwnProperty.call(object, property) ));",
+            output: "const hasProperty = (( Object.hasOwn(object, property) ));",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 24,
+                endLine: 1,
+                endColumn: 78
+            }]
+        },
+        {
+            code: "const hasProperty = (( Object.prototype.hasOwnProperty.call ))(object, property);",
+            output: "const hasProperty = (( Object.hasOwn ))(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 81
+            }]
+        },
+        {
+            code: "const hasProperty = (( Object.prototype.hasOwnProperty )).call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 81
+            }]
+        },
+        {
+            code: "const hasProperty = (( Object.prototype )).hasOwnProperty.call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 81
+            }]
+        },
+        {
+            code: "const hasProperty = (( Object )).prototype.hasOwnProperty.call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 81
+            }]
+        },
+        {
+            code: "const hasProperty = {}.hasOwnProperty.call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 61
+            }]
+        },
+        {
+            code: "const hasProperty={}.hasOwnProperty.call(object, property);",
+            output: "const hasProperty=Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 19,
+                endLine: 1,
+                endColumn: 59
+            }]
+        },
+        {
+            code: "const hasProperty = (( {}.hasOwnProperty.call(object, property) ));",
+            output: "const hasProperty = (( Object.hasOwn(object, property) ));",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 24,
+                endLine: 1,
+                endColumn: 64
+            }]
+        },
+        {
+            code: "const hasProperty = (( {}.hasOwnProperty.call ))(object, property);",
+            output: "const hasProperty = (( Object.hasOwn ))(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 67
+            }]
+        },
+        {
+            code: "const hasProperty = (( {}.hasOwnProperty )).call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 67
+            }]
+        },
+        {
+            code: "const hasProperty = (( {} )).hasOwnProperty.call(object, property);",
+            output: "const hasProperty = Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 67
+            }]
+        },
+        {
+            code: "function foo(){return {}.hasOwnProperty.call(object, property)}",
+            output: "function foo(){return Object.hasOwn(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 23,
+                endLine: 1,
+                endColumn: 63
+            }]
+        },
+
+        // https://github.com/eslint/eslint/pull/15346#issuecomment-991417335
+        {
+            code: "function foo(){return{}.hasOwnProperty.call(object, property)}",
+            output: "function foo(){return Object.hasOwn(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 22,
+                endLine: 1,
+                endColumn: 62
+            }]
+        },
+        {
+            code: "function foo(){return/*comment*/{}.hasOwnProperty.call(object, property)}",
+            output: "function foo(){return/*comment*/Object.hasOwn(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 33,
+                endLine: 1,
+                endColumn: 73
+            }]
+        },
+        {
+            code: "async function foo(){return await{}.hasOwnProperty.call(object, property)}",
+            output: "async function foo(){return await Object.hasOwn(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 34,
+                endLine: 1,
+                endColumn: 74
+            }]
+        },
+        {
+            code: "async function foo(){return await/*comment*/{}.hasOwnProperty.call(object, property)}",
+            output: "async function foo(){return await/*comment*/Object.hasOwn(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 45,
+                endLine: 1,
+                endColumn: 85
+            }]
+        },
+        {
+            code: "for (const x of{}.hasOwnProperty.call(object, property).toString());",
+            output: "for (const x of Object.hasOwn(object, property).toString());",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 16,
+                endLine: 1,
+                endColumn: 56
+            }]
+        },
+        {
+            code: "for (const x of/*comment*/{}.hasOwnProperty.call(object, property).toString());",
+            output: "for (const x of/*comment*/Object.hasOwn(object, property).toString());",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 27,
+                endLine: 1,
+                endColumn: 67
+            }]
+        },
+        {
+            code: "for (const x in{}.hasOwnProperty.call(object, property).toString());",
+            output: "for (const x in Object.hasOwn(object, property).toString());",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 16,
+                endLine: 1,
+                endColumn: 56
+            }]
+        },
+        {
+            code: "for (const x in/*comment*/{}.hasOwnProperty.call(object, property).toString());",
+            output: "for (const x in/*comment*/Object.hasOwn(object, property).toString());",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 27,
+                endLine: 1,
+                endColumn: 67
+            }]
+        },
+        {
+            code: "function foo(){return({}.hasOwnProperty.call)(object, property)}",
+            output: "function foo(){return(Object.hasOwn)(object, property)}",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 22,
+                endLine: 1,
+                endColumn: 64
+            }]
+        },
+        {
+            code: "Object['prototype']['hasOwnProperty']['call'](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 64
+            }]
+        },
+        {
+            code: "Object[`prototype`][`hasOwnProperty`][`call`](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 64
+            }]
+        },
+        {
+            code: "Object['hasOwnProperty']['call'](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 51
+            }]
+        },
+        {
+            code: "Object[`hasOwnProperty`][`call`](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 51
+            }]
+        },
+        {
+            code: "({})['hasOwnProperty']['call'](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 49
+            }]
+        },
+        {
+            code: "({})[`hasOwnProperty`][`call`](object, property);",
+            output: "Object.hasOwn(object, property);",
+            errors: [{
+                messageId: "useHasOwn",
+                line: 1,
+                column: 1,
+                endLine: 1,
+                endColumn: 49
+            }]
+        }
+    ]
+});
diff --git a/tests/lib/rules/prefer-regex-literals.js b/tests/lib/rules/prefer-regex-literals.js
index ccd88ae74..f2982cbfb 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')",
@@ -33,6 +35,7 @@ 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`)",
@@ -42,8 +45,10 @@ ruleTester.run("prefer-regex-literals", rule, {
         "new RegExp(String.raw`a${''}c`);",
         "new RegExp('a' + 'b')",
         "RegExp(1)",
-        "new RegExp(/a/, 'u');",
-        "new RegExp(/a/);",
+        "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 }]
@@ -134,124 +139,2338 @@ ruleTester.run("prefer-regex-literals", rule, {
     invalid: [
         {
             code: "new RegExp('abc');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('abc');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('abc', 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('abc', 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(`abc`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`abc`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`abc\nabc`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc\\nabc/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`\tabc\nabc`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\tabc\\nabc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`abc`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`abc`, String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`abc`, String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String['raw']`a`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('');",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('', '');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw``);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/(?:)/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp('a', `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(`a`, 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp(String.raw`a`, 'g');",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new RegExp(String.raw`\\d`, `g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String.raw`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String['raw']`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(String[\"raw\"]`\\\\d`, `g`);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\d/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "RegExp('a', String.raw`g`);",
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/g;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "new globalThis.RegExp('a');",
-            env: { es2020: true },
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression" }]
+            env: {
+                es2020: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
         {
             code: "globalThis.RegExp('a');",
-            env: { es2020: true },
-            errors: [{ messageId: "unexpectedRegExp", type: "CallExpression" }]
+            env: {
+                es2020: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "CallExpression",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
-
         {
             code: "new RegExp(/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');",
-            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`);",
-            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`);",
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRedundantRegExpWithFlags",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1
+                }
+            ]
         },
         {
             code: "new RegExp('a');",
-            options: [{ disallowRedundantWrapping: true }],
-            errors: [{ messageId: "unexpectedRegExp", type: "NewExpression", line: 1, column: 1 }]
+            options: [
+                {
+                    disallowRedundantWrapping: true
+                }
+            ],
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 1,
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
         },
-
-        // Optional chaining
         {
             code: "new RegExp((String?.raw)`a`);",
-            errors: [{ messageId: "unexpectedRegExp" }]
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('+');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('*');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('+');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('*');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('+', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('*', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('+', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('*', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('abc', 'u');",
+            parserOptions: {
+                ecmaVersion: 3
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "new RegExp('abc', 'd');",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('abc', 'd');",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/abc/d;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\\\\\', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\n', '');",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\n\\n', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\t', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\t\\t', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t\\t/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\r\\n', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\r\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u1234', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u{1234}', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\u{11111}', 'g')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\v', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\v\\v', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v\\v/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\f', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\f\\f', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f\\f/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\b\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\b\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\B\\\\b', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\B\\b/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\w', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\w/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new globalThis.RegExp('\\\\W', '');",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\W/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\s', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\s/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\S', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\d', '');",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\d/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\D', '')",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "globalThis.RegExp('\\\\\\\\\\\\D', '')",
+            globals: {
+                globalThis: "readonly"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\\\\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\D\\\\D', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\D\\D/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new globalThis.RegExp('\\\\0\\\\0', '');",
+            globals: {
+                globalThis: "writable"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\\\0\\\\0', '');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('\\0\\0', 'g');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\0\\\\0\\\\0', '')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\0\\0\\0/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp('\\\\78\\\\126\\\\5934', '')",
+            parserOptions: {
+                ecmaVersion: 2022
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\78\\126\\5934/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new window['RegExp']('\\\\x56\\\\x78\\\\x45', '');",
+            env: {
+                browser: true
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\x56\\x78\\x45/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a in(RegExp('abc'))",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a in(/abc/)"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "x = y\n            RegExp(\"foo\").test(x) ? bar() : baz()",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "func(new RegExp(String.raw`\\w{1, 2`, 'u'),new RegExp(String.raw`\\w{1, 2`, 'u'))",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "x = y;\n            RegExp(\"foo\").test(x) ? bar() : baz()",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "x = y;\n            /foo/.test(x) ? bar() : baz()"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "typeof RegExp(\"foo\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "typeof /foo/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/foo/ instanceof RegExp(String.raw`blahblah`, 'g') ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "RegExp(\"foo\") instanceof /blahblah/g ? typeof new RegExp('(\\\\p{Emoji_Presentation})\\\\1', `ug`) : false"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "RegExp(\"foo\") instanceof RegExp(String.raw`blahblah`, 'g') ? typeof /(\\p{Emoji_Presentation})\\1/ug : false"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "[   new RegExp(`someregular`)]",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "[   /someregular/]"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "const totallyValidatesEmails = new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")\n            if (typeof totallyValidatesEmails === 'object') {\n                runSomethingThatExists(Regexp('stuff'))\n            }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            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'",
+            errors: [
+                {
+                    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",
+                    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",
+                    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",
+                    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",
+                    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",
+                    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",
+                    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'"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "#!/usr/bin/sh\n            RegExp(\"foo\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "#!/usr/bin/sh\n            /foo/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "async function abc(){await new RegExp(\"foo\")}",
+            parserOptions: {
+                ecmaVersion: 8,
+                sourceType: "module"
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "function* abc(){yield new RegExp(\"foo\")}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "function* abc(){yield* new RegExp(\"foo\")}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "function* abc(){yield* /foo/}"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "console.log({ ...new RegExp('a') })",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "console.log({ .../a/ })"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "delete RegExp('a');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "delete /a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "void RegExp('a');",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "void /a/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**RegExp('a')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S+@(\\S+\\.)+\\S+/**RegExp('a')"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")**/a/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%RegExp('a')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\S+@(\\S+\\.)+\\S+/%RegExp('a')"
+                        }
+                    ]
+                },
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "new RegExp(\"\\\\S+@(\\\\S+\\\\.)+\\\\S+\")%/a/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a in RegExp('abc')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a in /abc/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ == new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ == /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ === new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ === /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ != new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ != /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ !== new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ !== /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ > new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ > /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ < new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ < /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ <= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ <= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ << new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ << /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >> new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >> /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ >>> new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ >>> /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ ^ new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ ^ /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ & new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ & /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            /abc/ | new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            /abc/ | /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            null ?? new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            null ?? /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc *= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc *= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            console.log({a: new RegExp('sup')})\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            console.log({a: /sup/})\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            console.log(() => {new RegExp('sup')})\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            console.log(() => {/sup/})\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            function abc() {new RegExp('sup')}\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            function abc() {/sup/}\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            function abc() {return new RegExp('sup')}\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            function abc() {return /sup/}\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc <<= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc <<= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc >>= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc >>= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc >>>= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc >>>= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ^= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ^= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc &= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc &= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc |= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc |= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ??= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ??= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc &&= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc &&= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc ||= new RegExp('cba');\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc ||= /cba/;\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc **= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc **= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc /= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc /= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc += new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc += /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc -= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc -= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            abc %= new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            abc %= /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "\n            () => new RegExp('blah')\n            ",
+            parserOptions: {
+                ecmaVersion: 2021
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "\n            () => /blah/\n            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a/RegExp(\"foo\")in b",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a/ /foo/ in b"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "a/RegExp(\"foo\")instanceof b",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "a/ /foo/ instanceof b"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "do RegExp(\"foo\")\nwhile (true);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "do /foo/\nwhile (true);"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for(let i;i<5;i++) { break\nnew RegExp('search')}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "for(let i;i<5;i++) { break\n/search/}"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for(let i;i<5;i++) { continue\nnew RegExp('search')}",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            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            ",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            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            "
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "throw new RegExp('abcdefg') // fail with a regular expression",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "throw /abcdefg/ // fail with a regular expression"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "for (value of new RegExp('something being searched')) { console.log(value) }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "(async function(){for await (value of new RegExp('something being searched')) { console.log(value) }})()",
+            parserOptions: {
+                ecmaVersion: 2018
+            },
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "for (value in new RegExp('something being searched')) { console.log(value) }",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "for (value in /something being searched/) { console.log(value) }"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "if (condition1 && condition2) new RegExp('avalue').test(str);",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
+        },
+        {
+            code: "debugger\nnew RegExp('myReg')",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "debugger\n/myReg/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\t\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\f\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\f/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\v\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\v/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "RegExp(\"\\\\\\r\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\r/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\t\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\t/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"/\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\//"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\.\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/./"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\.\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\./"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\\\n\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\\\\\n\\\\\\f\\\\\\n\")",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\f\\n/"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp(\"\\u000A\\u000A\");",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: [
+                        {
+                            messageId: "replaceWithLiteral",
+                            output: "/\\n\\n/;"
+                        }
+                    ]
+                }
+            ]
+        },
+        {
+            code: "new RegExp('mysafereg' /* comment explaining its safety */)",
+            errors: [
+                {
+                    messageId: "unexpectedRegExp",
+                    suggestions: null
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/prefer-template.js b/tests/lib/rules/prefer-template.js
index eea0255f1..a89a36a9d 100644
--- a/tests/lib/rules/prefer-template.js
+++ b/tests/lib/rules/prefer-template.js
@@ -223,6 +223,187 @@ ruleTester.run("prefer-template", rule, {
             code: "foo + '\\0'",
             output: "`${foo  }\\0`",
             errors
+        },
+
+        // https://github.com/eslint/eslint/issues/15083
+        {
+            code: `"default-src 'self' https://*.google.com;"
+            + "frame-ancestors 'none';"
+            + "report-to " + foo + ";"`,
+            output: `\`default-src 'self' https://*.google.com;\`
+            + \`frame-ancestors 'none';\`
+            + \`report-to \${  foo  };\``,
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo",
+            output: "`a` + `b${  foo}`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + 'c' + 'd'",
+            output: "`a` + `b${  foo  }c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + 'b + c' + foo + 'd' + 'e'",
+            output: "`a` + `b + c${  foo  }d` + `e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd')",
+            output: "`a` + `b${  foo  }c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('a' + 'b')",
+            output: "`a` + `b${  foo  }a` + `b`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd') + ('e' + 'f')",
+            output: "`a` + `b${  foo  }c` + `d` + `e` + `f`",
+            errors
+        },
+        {
+            code: "foo + ('a' + 'b') + ('c' + 'd')",
+            output: "`${foo  }a` + `b` + `c` + `d`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + 'c') + ('d' + bar + 'e')",
+            output: "`a${  foo  }b` + `c` + `d${  bar  }e`",
+            errors
+        },
+        {
+            code: "foo + ('b' + 'c') + ('d' + bar + 'e')",
+            output: "`${foo  }b` + `c` + `d${  bar  }e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + 'd' + 'e')",
+            output: "`a` + `b${  foo  }c` + `d` + `e`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + 'd')",
+            output: "`a` + `b${  foo  }c${  bar  }d`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + ('d' + 'e') + 'f')",
+            output: "`a` + `b${  foo  }c${  bar  }d` + `e` + `f`",
+            errors
+        },
+        {
+            code: "'a' + 'b' + foo + ('c' + bar + 'e') + 'f' + test",
+            output: "`a` + `b${  foo  }c${  bar  }e` + `f${  test}`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + bar + 'c') + ('d' + test)",
+            output: "`a${  foo  }b${  bar  }c` + `d${  test}`",
+            errors
+        },
+        {
+            code: "'a' + foo + ('b' + 'c') + ('d' + bar)",
+            output: "`a${  foo  }b` + `c` + `d${  bar}`",
+            errors
+        },
+        {
+            code: "foo + ('a' + bar + 'b') + 'c' + test",
+            output: "`${foo  }a${  bar  }b` + `c${  test}`",
+            errors
+        },
+        {
+            code: "'a' + '`b`' + c",
+            output: "`a` + `\\`b\\`${  c}`",
+            errors
+        },
+        {
+            code: "'a' + '`b` + `c`' + d",
+            output: "`a` + `\\`b\\` + \\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "'a' + b + ('`c`' + '`d`')",
+            output: "`a${  b  }\\`c\\`` + `\\`d\\``",
+            errors
+        },
+        {
+            code: "'`a`' + b + ('`c`' + '`d`')",
+            output: "`\\`a\\`${  b  }\\`c\\`` + `\\`d\\``",
+            errors
+        },
+        {
+            code: "foo + ('`a`' + bar + '`b`') + '`c`' + test",
+            output: "`${foo  }\\`a\\`${  bar  }\\`b\\`` + `\\`c\\`${  test}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c') + d",
+            output: "`a` + `b` + `c${  d}`",
+            errors
+        },
+        {
+            code: "'a' + ('`b`' + '`c`') + d",
+            output: "`a` + `\\`b\\`` + `\\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "a + ('b' + 'c') + d",
+            output: "`${a  }b` + `c${  d}`",
+            errors
+        },
+        {
+            code: "a + ('b' + 'c') + (d + 'e')",
+            output: "`${a  }b` + `c${  d  }e`",
+            errors
+        },
+        {
+            code: "a + ('`b`' + '`c`') + d",
+            output: "`${a  }\\`b\\`` + `\\`c\\`${  d}`",
+            errors
+        },
+        {
+            code: "a + ('`b` + `c`' + '`d`') + e",
+            output: "`${a  }\\`b\\` + \\`c\\`` + `\\`d\\`${  e}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c' + 'd') + e",
+            output: "`a` + `b` + `c` + `d${  e}`",
+            errors
+        },
+        {
+            code: "'a' + ('b' + 'c' + 'd' + (e + 'f') + 'g' +'h' + 'i') + j",
+            output: "`a` + `b` + `c` + `d${  e  }fg` +`h` + `i${  j}`",
+            errors
+        },
+        {
+            code: "a + (('b' + 'c') + 'd')",
+            output: "`${a  }b` + `c` + `d`",
+            errors
+        },
+        {
+            code: "(a + 'b') + ('c' + 'd') + e",
+            output: "`${a  }b` + `c` + `d${  e}`",
+            errors
+        },
+        {
+            code: "var foo = \"Hello \" + \"world \" + \"another \" + test",
+            output: "var foo = `Hello ` + `world ` + `another ${  test}`",
+            errors
+        },
+        {
+            code: "'Hello ' + '\"world\" ' + test",
+            output: "`Hello ` + `\"world\" ${  test}`",
+            errors
+        },
+        {
+            code: "\"Hello \" + \"'world' \" + test",
+            output: "`Hello ` + `'world' ${  test}`",
+            errors
         }
     ]
 });