Repository: eslint/eslint
Pull request #14841 (2021-07-27 03:01:01)

Chore: Adopt `eslint-plugin/prefer-message-ids` rule internally
<!--
    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/master/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
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[X] 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)

The public rule [eslint-plugin/prefer-message-ids](https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/blob/master/docs/rules/prefer-message-ids.md) is more robust than our internal version, and it's also valuable for us to dogfood this public rule as it's the same one that third-party plugin authors will use. So this PR deletes our custom version and switches us to the public rule for internal usage.

Follow-up to https://github.com/eslint/eslint/pull/14823.

CC: @aladdin-add

#### Is there anything you'd like reviewers to focus on?

No.

bmish: It is true that we can't always detect all usages of `context.report` since it may be used inside helper functions. If we're worried about that, how about I update `eslint-plugin/prefer-message-ids` to also flag a violation when `meta.messages` is missing? That's a new rule I just wrote and I would much prefer to have one comprehensive rule rather than rely on two.
mdjermanovic: > If we're worried about that, how about I update `eslint-plugin/prefer-message-ids` to also flag a violation when `meta.messages` is missing? That's a new rule I just wrote and I would much prefer to have one comprehensive rule (covering both situations) rather than rely on two.

Makes sense to me :+1: 
bmish: @mdjermanovic I have updated the rule to handle that case so this PR is ready to be merged :)

Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 9bb665a3c..b405b82fc 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -67,6 +67,7 @@ module.exports = {
         "eslint-plugin/consistent-output": "error",
         "eslint-plugin/no-deprecated-context-methods": "error",
         "eslint-plugin/no-only-tests": "error",
+        "eslint-plugin/prefer-message-ids": "error",
         "eslint-plugin/prefer-output-null": "error",
         "eslint-plugin/prefer-placeholders": "error",
         "eslint-plugin/prefer-replace-text": "error",
@@ -84,8 +85,7 @@ module.exports = {
             excludedFiles: ["index.js"],
             rules: {
                 "eslint-plugin/prefer-object-rule": "error",
-                "internal-rules/no-invalid-meta": "error",
-                "internal-rules/consistent-meta-messages": "error"
+                "internal-rules/no-invalid-meta": "error"
             }
         },
         {
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index ec53551c5..6aab5b566 100644
--- a/docs/developer-guide/nodejs-api.md
+++ b/docs/developer-guide/nodejs-api.md
@@ -355,7 +355,9 @@ The `LintResult` value is the information of the linting result of each file. Th
 * `fixableWarningCount` (`number`)<br>
   The number of warnings that can be fixed automatically by the `fix` constructor option.
 * `errorCount` (`number`)<br>
-  The number of errors. This includes fixable errors.
+  The number of errors. This includes fixable errors and fatal errors.
+* `fatalErrorCount` (`number`)<br>
+  The number of fatal errors.
 * `warningCount` (`number`)<br>
   The number of warnings. This includes fixable warnings.
 * `output` (`string | undefined`)<br>
diff --git a/docs/user-guide/command-line-interface.md b/docs/user-guide/command-line-interface.md
index 99fd61eb9..4500e6ff6 100644
--- a/docs/user-guide/command-line-interface.md
+++ b/docs/user-guide/command-line-interface.md
@@ -81,6 +81,7 @@ Miscellaneous:
   --init                         Run config initialization wizard - default: false
   --env-info                     Output execution environment information - default: false
   --no-error-on-unmatched-pattern  Prevent errors when pattern is unmatched - default: false
+  --exit-on-fatal-error          Exit with exit code 2 in case of fatal error - default: false
   --debug                        Output debugging information
   -h, --help                     Show help
   -v, --version                  Output the version number
@@ -467,6 +468,10 @@ This option outputs information about the execution environment, including the v
 
 This option prevents errors when a quoted glob pattern or `--ext` is unmatched. This will not prevent errors when your shell can't match a glob.
 
+#### `--exit-on-fatal-error`
+
+This option causes ESLint to exit with exit code 2 if one or more fatal parsing errors occur. Without this option, fatal parsing errors are reported as rule violations.
+
 #### `--debug`
 
 This option outputs debugging information to the console. This information is useful when you're seeing a problem and having a hard time pinpointing it. The ESLint team may ask for this debugging information to help solve bugs.
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index ca298f9c3..24f6a10d1 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -156,6 +156,9 @@ function calculateStatsPerFile(messages) {
     return messages.reduce((stat, message) => {
         if (message.fatal || message.severity === 2) {
             stat.errorCount++;
+            if (message.fatal) {
+                stat.fatalErrorCount++;
+            }
             if (message.fix) {
                 stat.fixableErrorCount++;
             }
@@ -168,6 +171,7 @@ function calculateStatsPerFile(messages) {
         return stat;
     }, {
         errorCount: 0,
+        fatalErrorCount: 0,
         warningCount: 0,
         fixableErrorCount: 0,
         fixableWarningCount: 0
@@ -183,12 +187,14 @@ function calculateStatsPerFile(messages) {
 function calculateStatsPerRun(results) {
     return results.reduce((stat, result) => {
         stat.errorCount += result.errorCount;
+        stat.fatalErrorCount += result.fatalErrorCount;
         stat.warningCount += result.warningCount;
         stat.fixableErrorCount += result.fixableErrorCount;
         stat.fixableWarningCount += result.fixableWarningCount;
         return stat;
     }, {
         errorCount: 0,
+        fatalErrorCount: 0,
         warningCount: 0,
         fixableErrorCount: 0,
         fixableWarningCount: 0
diff --git a/lib/cli.js b/lib/cli.js
index f76676454..477310da5 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -131,14 +131,16 @@ function translateOptions({
  */
 function countErrors(results) {
     let errorCount = 0;
+    let fatalErrorCount = 0;
     let warningCount = 0;
 
     for (const result of results) {
         errorCount += result.errorCount;
+        fatalErrorCount += result.fatalErrorCount;
         warningCount += result.warningCount;
     }
 
-    return { errorCount, warningCount };
+    return { errorCount, fatalErrorCount, warningCount };
 }
 
 /**
@@ -314,9 +316,12 @@ const cli = {
         if (await printResults(engine, resultsToPrint, options.format, options.outputFile)) {
 
             // Errors and warnings from the original unfiltered results should determine the exit code
-            const { errorCount, warningCount } = countErrors(results);
+            const { errorCount, fatalErrorCount, warningCount } = countErrors(results);
+
             const tooManyWarnings =
                 options.maxWarnings >= 0 && warningCount > options.maxWarnings;
+            const shouldExitForFatalErrors =
+                options.exitOnFatalError && fatalErrorCount > 0;
 
             if (!errorCount && tooManyWarnings) {
                 log.error(
@@ -325,6 +330,10 @@ const cli = {
                 );
             }
 
+            if (shouldExitForFatalErrors) {
+                return 2;
+            }
+
             return (errorCount || tooManyWarnings) ? 1 : 0;
         }
 
diff --git a/lib/options.js b/lib/options.js
index 92c140bd3..e3661ec81 100644
--- a/lib/options.js
+++ b/lib/options.js
@@ -290,6 +290,12 @@ module.exports = optionator({
             default: "true",
             description: "Prevent errors when pattern is unmatched"
         },
+        {
+            option: "exit-on-fatal-error",
+            type: "Boolean",
+            default: "false",
+            description: "Exit with exit code 2 in case of fatal error"
+        },
         {
             option: "debug",
             type: "Boolean",
diff --git a/lib/rules/comma-style.js b/lib/rules/comma-style.js
index fbdecccaa..824ad89b2 100644
--- a/lib/rules/comma-style.js
+++ b/lib/rules/comma-style.js
@@ -216,6 +216,8 @@ module.exports = {
                         previousItemToken = tokenAfterItem
                             ? sourceCode.getTokenBefore(tokenAfterItem)
                             : sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1];
+                    } else {
+                        previousItemToken = currentItemToken;
                     }
                 });
 
diff --git a/lib/rules/curly.js b/lib/rules/curly.js
index 92d31a647..61dcd8024 100644
--- a/lib/rules/curly.js
+++ b/lib/rules/curly.js
@@ -131,15 +131,6 @@ module.exports = {
             return token.value === "else" && token.type === "Keyword";
         }
 
-        /**
-         * Gets the `else` keyword token of a given `IfStatement` node.
-         * @param {ASTNode} node A `IfStatement` node to get.
-         * @returns {Token} The `else` keyword token.
-         */
-        function getElseKeyword(node) {
-            return node.alternate && sourceCode.getFirstTokenBetween(node.consequent, node.alternate, isElseKeywordToken);
-        }
-
         /**
          * Determines whether the given node has an `else` keyword token as the first token after.
          * @param {ASTNode} node The node to check.
@@ -361,7 +352,7 @@ module.exports = {
                         if (this.expected) {
                             context.report({
                                 node,
-                                loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+                                loc: body.loc,
                                 messageId: opts && opts.condition ? "missingCurlyAfterCondition" : "missingCurlyAfter",
                                 data: {
                                     name
@@ -371,7 +362,7 @@ module.exports = {
                         } else {
                             context.report({
                                 node,
-                                loc: (name !== "else" ? node : getElseKeyword(node)).loc.start,
+                                loc: body.loc,
                                 messageId: opts && opts.condition ? "unexpectedCurlyAfterCondition" : "unexpectedCurlyAfter",
                                 data: {
                                     name
diff --git a/package.json b/package.json
index ea08a90ef..1731ae6e1 100644
--- a/package.json
+++ b/package.json
@@ -96,7 +96,7 @@
     "ejs": "^3.0.2",
     "eslint": "file:.",
     "eslint-config-eslint": "file:packages/eslint-config-eslint",
-    "eslint-plugin-eslint-plugin": "^3.4.0",
+    "eslint-plugin-eslint-plugin": "^3.5.3",
     "eslint-plugin-internal-rules": "file:tools/internal-rules",
     "eslint-plugin-jsdoc": "^25.4.3",
     "eslint-plugin-node": "^11.1.0",
diff --git a/tools/internal-rules/consistent-meta-messages.js b/tools/internal-rules/consistent-meta-messages.js
deleted file mode 100644
index b094c86e8..000000000
--- a/tools/internal-rules/consistent-meta-messages.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * @fileoverview A rule to enforce using `meta.messages` property in core rules
- * @author 薛定谔的猫<hh_2013@foxmail.com>
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-/**
- * Gets the property of the Object node passed in that has the name specified.
- * @param {string} property Name of the property to return.
- * @param {ASTNode} node The ObjectExpression node.
- * @returns {ASTNode} The Property node or null if not found.
- */
-function getPropertyFromObject(property, node) {
-    const properties = node.properties;
-
-    for (let i = 0; i < properties.length; i++) {
-        if (properties[i].key.name === property) {
-            return properties[i];
-        }
-    }
-
-    return null;
-}
-
-/**
- * Verifies that the meta.messages property is present.
- * TODO: check it has the correct value
- * @param {RuleContext} context The ESLint rule context.
- * @param {ASTNode} exportsNode ObjectExpression node that the rule exports.
- * @returns {void}
- */
-function checkMetaMessages(context, exportsNode) {
-    if (exportsNode.type !== "ObjectExpression") {
-
-        // if the exported node is not the correct format, "internal-no-invalid-meta" will already report this.
-        return;
-    }
-
-    const metaProperty = getPropertyFromObject("meta", exportsNode);
-    const messages = metaProperty && getPropertyFromObject("messages", metaProperty.value);
-
-    if (!messages) {
-        context.report({
-            node: metaProperty,
-            messageId: "expectedMessages"
-        });
-    }
-}
-
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
-
-module.exports = {
-    meta: {
-        docs: {
-            description: "enforce using `meta.messages` property in core rules",
-            category: "Internal",
-            recommended: false
-        },
-        schema: [],
-        type: "suggestion",
-        messages: {
-            expectedMessages: "Expected `meta.messages` property."
-        }
-    },
-
-    create(context) {
-        return {
-            "AssignmentExpression[left.object.name='module'][left.property.name='exports']"(node) {
-                checkMetaMessages(context, node.right);
-            }
-        };
-    }
-};


Test patch:
diff --git a/tests/bin/eslint.js b/tests/bin/eslint.js
index 7500d6611..4fed66aed 100644
--- a/tests/bin/eslint.js
+++ b/tests/bin/eslint.js
@@ -89,6 +89,7 @@ describe("bin/eslint.js", () => {
                     filePath: "<text>",
                     messages: [],
                     errorCount: 0,
+                    fatalErrorCount: 0,
                     warningCount: 0,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
@@ -117,6 +118,14 @@ describe("bin/eslint.js", () => {
             return assertExitCode(child, 1);
         });
 
+        it("has exit code 2 if a syntax error is thrown when exit-on-fatal-error is true", () => {
+            const child = runESLint(["--stdin", "--no-eslintrc", "--exit-on-fatal-error"]);
+
+            child.stdin.write("This is not valid JS syntax.\n");
+            child.stdin.end();
+            return assertExitCode(child, 2);
+        });
+
         it("has exit code 1 if a linting error occurs", () => {
             const child = runESLint(["--stdin", "--no-eslintrc", "--rule", "semi:2"]);
 
diff --git a/tests/fixtures/exit-on-fatal-error/fatal-error.js b/tests/fixtures/exit-on-fatal-error/fatal-error.js
new file mode 100644
index 000000000..53a47a5b7
--- /dev/null
+++ b/tests/fixtures/exit-on-fatal-error/fatal-error.js
@@ -0,0 +1,1 @@
+var foo  1
\ No newline at end of file
diff --git a/tests/fixtures/exit-on-fatal-error/no-fatal-error-rule-violation.js b/tests/fixtures/exit-on-fatal-error/no-fatal-error-rule-violation.js
new file mode 100644
index 000000000..a23ad4a79
--- /dev/null
+++ b/tests/fixtures/exit-on-fatal-error/no-fatal-error-rule-violation.js
@@ -0,0 +1,3 @@
+/*eslint no-unused-vars: "error"*/
+
+var foo = 1;
\ No newline at end of file
diff --git a/tests/fixtures/exit-on-fatal-error/no-fatal-error.js b/tests/fixtures/exit-on-fatal-error/no-fatal-error.js
new file mode 100644
index 000000000..d5814b856
--- /dev/null
+++ b/tests/fixtures/exit-on-fatal-error/no-fatal-error.js
@@ -0,0 +1,1 @@
+var foo = 1;
\ No newline at end of file
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index 59243b0b7..680317b29 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -144,6 +144,7 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results.length, 1);
             assert.strictEqual(report.errorCount, 5);
             assert.strictEqual(report.warningCount, 0);
+            assert.strictEqual(report.fatalErrorCount, 0);
             assert.strictEqual(report.fixableErrorCount, 3);
             assert.strictEqual(report.fixableWarningCount, 0);
             assert.strictEqual(report.results[0].messages.length, 5);
@@ -310,6 +311,7 @@ describe("CLIEngine", () => {
                         messages: [],
                         errorCount: 0,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var bar = foo;"
@@ -317,6 +319,7 @@ describe("CLIEngine", () => {
                 ],
                 errorCount: 0,
                 warningCount: 0,
+                fatalErrorCount: 0,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 usedDeprecatedRules: []
@@ -519,6 +522,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         source: "var bar = foo"
@@ -526,6 +530,7 @@ describe("CLIEngine", () => {
                 ],
                 errorCount: 1,
                 warningCount: 0,
+                fatalErrorCount: 0,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 usedDeprecatedRules: []
@@ -562,6 +567,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 1,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var bar = foothis is a syntax error."
@@ -569,6 +575,7 @@ describe("CLIEngine", () => {
                 ],
                 errorCount: 1,
                 warningCount: 0,
+                fatalErrorCount: 1,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 usedDeprecatedRules: []
@@ -604,6 +611,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 1,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         source: "var bar ="
@@ -611,6 +619,7 @@ describe("CLIEngine", () => {
                 ],
                 errorCount: 1,
                 warningCount: 0,
+                fatalErrorCount: 1,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 usedDeprecatedRules: []
@@ -692,6 +701,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 1,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         source: "var bar = foothis is a syntax error.\n return bar;"
@@ -699,6 +709,7 @@ describe("CLIEngine", () => {
                 ],
                 errorCount: 1,
                 warningCount: 0,
+                fatalErrorCount: 1,
                 fixableErrorCount: 0,
                 fixableWarningCount: 0,
                 usedDeprecatedRules: []
@@ -1684,6 +1695,7 @@ describe("CLIEngine", () => {
                         messages: [],
                         errorCount: 0,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "true ? \"yes\" : \"no\";\n"
@@ -1693,6 +1705,7 @@ describe("CLIEngine", () => {
                         messages: [],
                         errorCount: 0,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0
                     },
@@ -1713,6 +1726,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n"
@@ -1734,6 +1748,7 @@ describe("CLIEngine", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var msg = \"hi\" + foo;\n"
@@ -5077,6 +5092,7 @@ describe("CLIEngine", () => {
                             ],
                             errorCount: 1,
                             warningCount: 0,
+                            fatalErrorCount: 0,
                             fixableErrorCount: 0,
                             fixableWarningCount: 0,
                             source: "/* eslint-disable */"
@@ -5084,6 +5100,7 @@ describe("CLIEngine", () => {
                     ],
                     errorCount: 1,
                     warningCount: 0,
+                    fatalErrorCount: 0,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     usedDeprecatedRules: []
@@ -6155,7 +6172,8 @@ describe("CLIEngine", () => {
                             }
                         ],
                         source: "a == b",
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6177,7 +6195,8 @@ describe("CLIEngine", () => {
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         messages: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6223,7 +6242,8 @@ describe("CLIEngine", () => {
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         messages: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6258,7 +6278,8 @@ describe("CLIEngine", () => {
                             }
                         ],
                         source: "a == b",
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index d1fea182d..dbfe03c26 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -803,6 +803,38 @@ describe("cli", () => {
         });
     });
 
+    describe("when given the exit-on-fatal-error flag", () => {
+        it("should not change exit code if no fatal errors are reported", async () => {
+            const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error.js");
+            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+
+            assert.strictEqual(exitCode, 0);
+        });
+
+        it("should exit with exit code 1 if no fatal errors are found, but rule violations are found", async () => {
+            const filePath = getFixturePath("exit-on-fatal-error", "no-fatal-error-rule-violation.js");
+            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+
+            assert.strictEqual(exitCode, 1);
+        });
+
+        it("should exit with exit code 2 if fatal error is found", async () => {
+            const filePath = getFixturePath("exit-on-fatal-error", "fatal-error.js");
+            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+
+            assert.strictEqual(exitCode, 2);
+        });
+
+        it("should exit with exit code 2 if fatal error is found in any file", async () => {
+            const filePath = getFixturePath("exit-on-fatal-error");
+            const exitCode = await cli.execute(`--no-ignore --exit-on-fatal-error ${filePath}`);
+
+            assert.strictEqual(exitCode, 2);
+        });
+
+
+    });
+
     describe("when passed --no-inline-config", () => {
         let localCLI;
 
diff --git a/tests/lib/eslint/eslint.js b/tests/lib/eslint/eslint.js
index c5a1b7360..aa35b842e 100644
--- a/tests/lib/eslint/eslint.js
+++ b/tests/lib/eslint/eslint.js
@@ -397,6 +397,7 @@ describe("ESLint", () => {
                     messages: [],
                     errorCount: 0,
                     warningCount: 0,
+                    fatalErrorCount: 0,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     output: "var bar = foo;",
@@ -597,6 +598,7 @@ describe("ESLint", () => {
                     ],
                     errorCount: 1,
                     warningCount: 0,
+                    fatalErrorCount: 0,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     source: "var bar = foo",
@@ -636,6 +638,7 @@ describe("ESLint", () => {
                     ],
                     errorCount: 1,
                     warningCount: 0,
+                    fatalErrorCount: 1,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     output: "var bar = foothis is a syntax error.",
@@ -674,6 +677,7 @@ describe("ESLint", () => {
                     ],
                     errorCount: 1,
                     warningCount: 0,
+                    fatalErrorCount: 1,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     source: "var bar =",
@@ -761,6 +765,7 @@ describe("ESLint", () => {
                     ],
                     errorCount: 1,
                     warningCount: 0,
+                    fatalErrorCount: 1,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
                     source: "var bar = foothis is a syntax error.\n return bar;",
@@ -1658,6 +1663,7 @@ describe("ESLint", () => {
                         messages: [],
                         errorCount: 0,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "true ? \"yes\" : \"no\";\n",
@@ -1668,6 +1674,7 @@ describe("ESLint", () => {
                         messages: [],
                         errorCount: 0,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         usedDeprecatedRules: []
@@ -1689,6 +1696,7 @@ describe("ESLint", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
@@ -1711,6 +1719,7 @@ describe("ESLint", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         output: "var msg = \"hi\" + foo;\n",
@@ -5006,6 +5015,7 @@ describe("ESLint", () => {
                         ],
                         errorCount: 1,
                         warningCount: 0,
+                        fatalErrorCount: 0,
                         fixableErrorCount: 0,
                         fixableWarningCount: 0,
                         source: "/* eslint-disable */",
@@ -6060,7 +6070,8 @@ describe("ESLint", () => {
                         ],
                         source: "a == b",
                         usedDeprecatedRules: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6083,7 +6094,8 @@ describe("ESLint", () => {
                         fixableWarningCount: 0,
                         messages: [],
                         usedDeprecatedRules: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6130,7 +6142,8 @@ describe("ESLint", () => {
                         fixableWarningCount: 0,
                         messages: [],
                         usedDeprecatedRules: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
@@ -6166,7 +6179,8 @@ describe("ESLint", () => {
                         ],
                         source: "a == b",
                         usedDeprecatedRules: [],
-                        warningCount: 0
+                        warningCount: 0,
+                        fatalErrorCount: 0
                     }
                 ]);
             });
diff --git a/tests/lib/rules/comma-style.js b/tests/lib/rules/comma-style.js
index 1eb308254..e0ac78d68 100644
--- a/tests/lib/rules/comma-style.js
+++ b/tests/lib/rules/comma-style.js
@@ -233,7 +233,45 @@ ruleTester.run("comma-style", rule, {
                     NewExpression: true
                 }
             }]
+        },
+        "var foo = [\n , \n 1, \n 2 \n];",
+        {
+            code: "const [\n , \n , \n a, \n b, \n] = arr;",
+            options: ["last", {
+                exceptions: {
+                    ArrayPattern: false
+                }
+            }],
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
+        {
+            code: "const [\n ,, \n a, \n b, \n] = arr;",
+            options: ["last", {
+                exceptions: {
+                    ArrayPattern: false
+                }
+            }],
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
+        {
+            code: "const arr = [\n 1 \n , \n ,2 \n]",
+            options: ["first"],
+            parserOptions: {
+                ecmaVersion: 6
+            }
+        },
+        {
+            code: "const arr = [\n ,'fifi' \n]",
+            options: ["first"],
+            parserOptions: {
+                ecmaVersion: 6
+            }
         }
+
     ],
 
     invalid: [
diff --git a/tests/lib/rules/curly.js b/tests/lib/rules/curly.js
index 155eec994..c8121fe5d 100644
--- a/tests/lib/rules/curly.js
+++ b/tests/lib/rules/curly.js
@@ -429,7 +429,26 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfterCondition",
                     data: { name: "if" },
-                    type: "IfStatement"
+                    type: "IfStatement",
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 15
+                }
+            ]
+        },
+        {
+            code: "if (foo) \n bar()",
+            output: "if (foo) \n {bar()}",
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "if" },
+                    type: "IfStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 7
                 }
             ]
         },
@@ -462,7 +481,26 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfterCondition",
                     data: { name: "while" },
-                    type: "WhileStatement"
+                    type: "WhileStatement",
+                    line: 1,
+                    column: 13,
+                    endLine: 1,
+                    endColumn: 18
+                }
+            ]
+        },
+        {
+            code: "while (foo) \n bar()",
+            output: "while (foo) \n {bar()}",
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "while" },
+                    type: "WhileStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 7
                 }
             ]
         },
@@ -473,7 +511,26 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfter",
                     data: { name: "do" },
-                    type: "DoWhileStatement"
+                    type: "DoWhileStatement",
+                    line: 1,
+                    column: 4,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "do \n bar(); while (foo)",
+            output: "do \n {bar();} while (foo)",
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "do" },
+                    type: "DoWhileStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 8
                 }
             ]
         },
@@ -507,7 +564,93 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfter",
                     data: { name: "for-of" },
-                    type: "ForOfStatement"
+                    type: "ForOfStatement",
+                    line: 1,
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 38
+                }
+            ]
+        },
+        {
+            code: "for (var foo of bar) \n console.log(foo)",
+            output: "for (var foo of bar) \n {console.log(foo)}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "for-of" },
+                    type: "ForOfStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 18
+                }
+            ]
+        },
+        {
+            code: "for (a;;) console.log(foo)",
+            output: "for (a;;) {console.log(foo)}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "for" },
+                    type: "ForStatement",
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 27
+                }
+            ]
+        },
+        {
+            code: "for (a;;) \n console.log(foo)",
+            output: "for (a;;) \n {console.log(foo)}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "for" },
+                    type: "ForStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 18
+                }
+            ]
+        },
+        {
+            code: "for (var foo of bar) {console.log(foo)}",
+            output: "for (var foo of bar) console.log(foo)",
+            options: ["multi"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfter",
+                    data: { name: "for-of" },
+                    type: "ForOfStatement",
+                    line: 1,
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 40
+                }
+            ]
+        },
+        {
+            code: "do{foo();} while(bar);",
+            output: "do foo(); while(bar);",
+            options: ["multi"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfter",
+                    data: { name: "do" },
+                    type: "DoWhileStatement",
+                    line: 1,
+                    column: 3,
+                    endLine: 1,
+                    endColumn: 11
                 }
             ]
         },
@@ -519,7 +662,26 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfterCondition",
                     data: { name: "for" },
-                    type: "ForStatement"
+                    type: "ForStatement",
+                    line: 1,
+                    column: 13,
+                    endLine: 1,
+                    endColumn: 22
+                }
+            ]
+        },
+        {
+            code: "for (;foo;) \n bar()",
+            output: "for (;foo;) \n {bar()}",
+            errors: [
+                {
+                    data: { name: "for" },
+                    type: "ForStatement",
+                    messageId: "missingCurlyAfterCondition",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 7
                 }
             ]
         },
@@ -531,7 +693,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfterCondition",
                     data: { name: "if" },
-                    type: "IfStatement"
+                    type: "IfStatement",
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 19
                 }
             ]
         },
@@ -567,7 +733,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfterCondition",
                     data: { name: "while" },
-                    type: "WhileStatement"
+                    type: "WhileStatement",
+                    line: 1,
+                    column: 13,
+                    endLine: 1,
+                    endColumn: 22
                 }
             ]
         },
@@ -653,7 +823,9 @@ ruleTester.run("curly", rule, {
                     data: { name: "else" },
                     type: "IfStatement",
                     line: 6,
-                    column: 3
+                    column: 8,
+                    endLine: 11,
+                    endColumn: 2
                 }
             ]
         },
@@ -665,7 +837,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfter",
                     data: { name: "for-in" },
-                    type: "ForInStatement"
+                    type: "ForInStatement",
+                    line: 1,
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 42
                 }
             ]
         },
@@ -690,7 +866,26 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfterCondition",
                     data: { name: "if" },
-                    type: "IfStatement"
+                    type: "IfStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 7
+                }
+            ]
+        },
+        {
+            code: "if (foo) baz()",
+            output: "if (foo) {baz()}",
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "if" },
+                    type: "IfStatement",
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         },
@@ -742,6 +937,22 @@ ruleTester.run("curly", rule, {
                 }
             ]
         },
+        {
+            code: "do foo(); while (bar)",
+            output: "do {foo();} while (bar)",
+            options: ["all"],
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "do" },
+                    type: "DoWhileStatement",
+                    line: 1,
+                    column: 4,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
         {
             code: "do \n foo(); \n while (bar)",
             output: "do \n {foo();} \n while (bar)",
@@ -750,7 +961,27 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfter",
                     data: { name: "do" },
-                    type: "DoWhileStatement"
+                    type: "DoWhileStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 8
+                }
+            ]
+        },
+        {
+            code: "for (var foo in bar) {console.log(foo)}",
+            output: "for (var foo in bar) console.log(foo)",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfter",
+                    data: { name: "for-in" },
+                    type: "ForInStatement",
+                    line: 1,
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 40
                 }
             ]
         },
@@ -787,7 +1018,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfter",
                     data: { name: "for-of" },
-                    type: "ForOfStatement"
+                    type: "ForOfStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 18
                 }
             ]
         },
@@ -910,7 +1145,45 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfterCondition",
                     data: { name: "for" },
-                    type: "ForStatement"
+                    type: "ForStatement",
+                    line: 1,
+                    column: 27,
+                    endLine: 3,
+                    endColumn: 3
+                }
+            ]
+        },
+        {
+            code: "for (var foo in bar) if (foo) console.log(1); else console.log(2);",
+            output: "for (var foo in bar) {if (foo) console.log(1); else console.log(2);}",
+            options: ["all"],
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "for-in" },
+                    type: "ForInStatement",
+                    line: 1,
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 67
+                },
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "if" },
+                    type: "IfStatement",
+                    line: 1,
+                    column: 31,
+                    endLine: 1,
+                    endColumn: 46
+                },
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "else" },
+                    type: "IfStatement",
+                    line: 1,
+                    column: 52,
+                    endLine: 1,
+                    endColumn: 67
                 }
             ]
         },
@@ -922,7 +1195,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "missingCurlyAfter",
                     data: { name: "for-in" },
-                    type: "ForInStatement"
+                    type: "ForInStatement",
+                    line: 2,
+                    column: 2,
+                    endLine: 3,
+                    endColumn: 22
                 }
             ]
         },
@@ -996,7 +1273,11 @@ ruleTester.run("curly", rule, {
                 {
                     messageId: "unexpectedCurlyAfter",
                     data: { name: "else" },
-                    type: "IfStatement"
+                    type: "IfStatement",
+                    line: 1,
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 33
                 }
             ]
         },
@@ -1041,6 +1322,70 @@ ruleTester.run("curly", rule, {
                 }
             ]
         },
+        {
+            code: "do\n{foo();} while (bar)",
+            output: "do\nfoo(); while (bar)",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfter",
+                    data: { name: "do" },
+                    type: "DoWhileStatement",
+                    line: 2,
+                    column: 1,
+                    endLine: 2,
+                    endColumn: 9
+                }
+            ]
+        },
+        {
+            code: "while (bar) { foo(); }",
+            output: "while (bar)  foo(); ",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfterCondition",
+                    data: { name: "while" },
+                    type: "WhileStatement",
+                    line: 1,
+                    column: 13,
+                    endLine: 1,
+                    endColumn: 23
+                }
+            ]
+        },
+        {
+            code: "while (bar) \n{\n foo(); }",
+            output: "while (bar) \n\n foo(); ",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfterCondition",
+                    data: { name: "while" },
+                    type: "WhileStatement",
+                    line: 2,
+                    column: 1,
+                    endLine: 3,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "for (;;) { foo(); }",
+            output: "for (;;)  foo(); ",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfterCondition",
+                    data: { name: "for" },
+                    type: "ForStatement",
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 20
+                }
+            ]
+        },
         {
             code: "do{[1, 2, 3].map(bar);} while (bar)",
             output: "do[1, 2, 3].map(bar); while (bar)",
@@ -1313,7 +1658,132 @@ ruleTester.run("curly", rule, {
             code: "if (a) { while (cond) if (b) foo() } else bar();",
             output: "if (a) { while (cond) if (b) foo() } else {bar();}",
             options: ["multi", "consistent"],
-            errors: [{ messageId: "missingCurlyAfter", data: { name: "else" }, type: "IfStatement" }]
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "else" },
+                    type: "IfStatement",
+                    line: 1,
+                    column: 43,
+                    endLine: 1,
+                    endColumn: 49
+                }
+            ]
+        },
+        {
+            code: "if (a)  while (cond) if (b) foo()  \nelse\n {bar();}",
+            output: "if (a)  while (cond) if (b) foo()  \nelse\n bar();",
+            options: ["multi", "consistent"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfter",
+                    data: { name: "else" },
+                    type: "IfStatement",
+                    line: 3,
+                    column: 2,
+                    endLine: 3,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "if (a) foo() \nelse\n bar();",
+            output: "if (a) {foo()} \nelse\n {bar();}",
+            errors: [{
+                type: "IfStatement",
+                messageId: "missingCurlyAfterCondition",
+                line: 1,
+                column: 8,
+                endLine: 1,
+                endColumn: 13
+            },
+            {
+                type: "IfStatement",
+                messageId: "missingCurlyAfter",
+                line: 3,
+                column: 2,
+                endLine: 3,
+                endColumn: 8
+            }]
+        },
+        {
+            code: "if (a) { while (cond) if (b) foo() } ",
+            output: "if (a)  while (cond) if (b) foo()  ",
+            options: ["multi", "consistent"],
+            errors: [{
+                messageId: "unexpectedCurlyAfterCondition",
+                data: { name: "if" },
+                type: "IfStatement",
+                line: 1,
+                column: 8,
+                endLine: 1,
+                endColumn: 37
+            }]
+        },
+        {
+            code: "if(a) { if (b) foo(); } if (c) bar(); else if(foo){bar();}",
+            output: "if(a)  if (b) foo();  if (c) bar(); else if(foo)bar();",
+            options: ["multi-or-nest"],
+            errors: [{
+                type: "IfStatement",
+                data: { name: "if" },
+                messageId: "unexpectedCurlyAfterCondition",
+                line: 1,
+                column: 7,
+                endLine: 1,
+                endColumn: 24
+            },
+            {
+                type: "IfStatement",
+                data: { name: "if" },
+                messageId: "unexpectedCurlyAfterCondition",
+                line: 1,
+                column: 51,
+                endLine: 1,
+                endColumn: 59
+            }]
+        },
+        {
+            code: "if (true) [1, 2, 3]\n.bar()",
+            output: "if (true) {[1, 2, 3]\n.bar()}",
+            options: ["multi-line"],
+            errors: [{
+                data: { name: "if" },
+                type: "IfStatement",
+                messageId: "missingCurlyAfterCondition",
+                line: 1,
+                column: 11,
+                endLine: 2,
+                endColumn: 7
+            }]
+        },
+        {
+            code: "for(\n;\n;\n) {foo()}",
+            output: "for(\n;\n;\n) foo()",
+            options: ["multi"],
+            errors: [{
+                data: { name: "for" },
+                type: "ForStatement",
+                messageId: "unexpectedCurlyAfterCondition",
+                line: 4,
+                column: 3,
+                endLine: 4,
+                endColumn: 10
+            }]
+        },
+        {
+            code: "for(\n;\n;\n) \nfoo()\n",
+            output: "for(\n;\n;\n) \n{foo()}\n",
+            options: ["multi-line"],
+            errors: [{
+                data: { name: "for" },
+                type: "ForStatement",
+                messageId: "missingCurlyAfterCondition",
+                line: 5,
+                column: 1,
+                endLine: 5,
+                endColumn: 6
+            }]
         },
         {
 
@@ -1330,6 +1800,46 @@ ruleTester.run("curly", rule, {
                 { messageId: "unexpectedCurlyAfterCondition", data: { name: "if" }, type: "IfStatement" },
                 { messageId: "unexpectedCurlyAfterCondition", data: { name: "while" }, type: "WhileStatement" }
             ]
+        },
+        {
+            code: "for(;;)foo()\n",
+            output: "for(;;){foo()}\n",
+            errors: [{
+                data: { name: "for" },
+                type: "ForStatement",
+                messageId: "missingCurlyAfterCondition",
+                line: 1,
+                column: 8,
+                endLine: 1,
+                endColumn: 13
+            }]
+        },
+        {
+            code: "for(var \ni \n in \n z)foo()\n",
+            output: "for(var \ni \n in \n z){foo()}\n",
+            errors: [{
+                data: { name: "for-in" },
+                type: "ForInStatement",
+                messageId: "missingCurlyAfter",
+                line: 4,
+                column: 4,
+                endLine: 4,
+                endColumn: 9
+            }]
+        },
+        {
+            code: "for(var i of \n z)\nfoo()\n",
+            output: "for(var i of \n z)\n{foo()}\n",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                data: { name: "for-of" },
+                type: "ForOfStatement",
+                messageId: "missingCurlyAfter",
+                line: 3,
+                column: 1,
+                endLine: 3,
+                endColumn: 6
+            }]
         }
     ]
 });
diff --git a/tests/tools/internal-rules/consistent-meta-messages.js b/tests/tools/internal-rules/consistent-meta-messages.js
deleted file mode 100644
index 4df8be92a..000000000
--- a/tests/tools/internal-rules/consistent-meta-messages.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * @fileoverview Tests for consistent-meta-messages rule.
- * @author 薛定谔的猫<hh_2013@foxmail.com>
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const rule = require("../../../tools/internal-rules/consistent-meta-messages");
-const { RuleTester } = require("../../../lib/rule-tester");
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-const ruleTester = new RuleTester();
-
-ruleTester.run("consistent-meta-messages", rule, {
-    valid: [
-        `module.exports = {
-            meta: {
-                messages: {unexpected: "an error occurs."}
-            }
-        };`
-    ],
-    invalid: [
-        {
-            code: `
-            module.exports = {
-                meta: {}
-            };`,
-            errors: [{ messageId: "expectedMessages" }]
-        }
-    ]
-});