Repository: eslint/eslint
Pull request #14766 (2021-07-04 08:57:30)

Update: change reporting location for `curly` rule (refs #12334)
<!--
    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))
[X] 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
[ ] 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)

Refers https://github.com/eslint/eslint/issues/12334

Fixes https://github.com/eslint/eslint/pull/13282

#### Is there anything you'd like reviewers to focus on?
No


Patch:
diff --git a/.eslintrc.js b/.eslintrc.js
index 668bc2747..9bb665a3c 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -66,10 +66,13 @@ module.exports = {
     rules: {
         "eslint-plugin/consistent-output": "error",
         "eslint-plugin/no-deprecated-context-methods": "error",
+        "eslint-plugin/no-only-tests": "error",
         "eslint-plugin/prefer-output-null": "error",
         "eslint-plugin/prefer-placeholders": "error",
+        "eslint-plugin/prefer-replace-text": "error",
         "eslint-plugin/report-message-format": ["error", "[^a-z].*\\.$"],
         "eslint-plugin/require-meta-docs-description": "error",
+        "eslint-plugin/require-meta-schema": "error",
         "eslint-plugin/require-meta-type": "error",
         "eslint-plugin/test-case-property-ordering": "error",
         "eslint-plugin/test-case-shorthand-strings": "error",
@@ -80,6 +83,7 @@ module.exports = {
             files: ["lib/rules/*", "tools/internal-rules/*"],
             excludedFiles: ["index.js"],
             rules: {
+                "eslint-plugin/prefer-object-rule": "error",
                 "internal-rules/no-invalid-meta": "error",
                 "internal-rules/consistent-meta-messages": "error"
             }
@@ -88,7 +92,7 @@ module.exports = {
             files: ["lib/rules/*"],
             excludedFiles: ["index.js"],
             rules: {
-                "internal-rules/consistent-docs-url": "error"
+                "eslint-plugin/require-meta-docs-url": ["error", { pattern: "https://eslint.org/docs/rules/{{name}}" }]
             }
         },
         {
diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.md b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
index 9b46d2944..b368e5009 100644
--- a/.github/ISSUE_TEMPLATE/BUG_REPORT.md
+++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.md
@@ -72,7 +72,7 @@ assignees: ''
 <!-- Please tell us exactly how to see the issue you're describing -->
 
 1. 
-1. 
-1. 
+2. 
+3. 
 
 **Are you willing to submit a pull request to fix this bug?**
diff --git a/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md b/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md
new file mode 100644
index 000000000..e03cb6e11
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/NEW_SYNTAX.md
@@ -0,0 +1,43 @@
+---
+name: "\U0001F4DD Request new syntax support"
+about: Request new stage 4 syntax be supported.
+title: ''
+labels:
+    - core
+    - new syntax
+assignees: ''
+
+---
+
+<!--
+    ESLint adheres to the Open JS Foundation Code of Conduct:
+    https://eslint.org/conduct
+-->
+
+**What is the name of the syntax to implement?**
+
+<!-- for example, "class fields" -->
+
+**Please provide the TC39 URL for the syntax proposal:**
+
+
+
+**Please provide some example code for the new syntax:**
+
+```js
+// example code here
+```
+
+## Implementation Checklist
+
+Please check off all items that have already been completed. Be sure to paste the pull request URLs next to each item so we can verify the work as done.
+
+- [ ] Ecma262 update: <!-- paste PR URL for this syntax here -->
+- [ ] ESTree update: <!-- paste PR URL for this ESTree update here -->
+- [ ] Acorn update: <!-- paste PR URL for this syntax here -->
+- [ ] `eslint-visitor-keys` update: <!-- paste PR URL for this syntax here -->
+- [ ] `espree` update: <!-- paste PR URL for this syntax here -->
+- [ ] `eslint-scope` update: <!-- paste PR URL for this syntax here -->
+- [ ] `eslint` update: <!-- paste PR URL for this syntax here -->
+
+**Are you willing to submit a pull request to implement this syntax?**
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6ba0bdc38..b1972878e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v2
-    - uses: actions/setup-node@v1
+    - uses: actions/setup-node@v2
     - name: Install Packages
       run: npm install
     - name: Lint Files
@@ -35,7 +35,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v2
-    - uses: actions/setup-node@v1
+    - uses: actions/setup-node@v2
       with:
         node-version: ${{ matrix.node }}
     - name: Install Packages
@@ -50,7 +50,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v2
-    - uses: actions/setup-node@v1
+    - uses: actions/setup-node@v2
       with:
         node-version: '12'
     - name: Install Packages
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f4a316be0..bd7fb6b5e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,16 @@
+v7.31.0 - July 17, 2021
+
+* [`efdbb12`](https://github.com/eslint/eslint/commit/efdbb1227019427ec2d968a8d6e9151dd8a77c35) Upgrade: @eslint/eslintrc to v0.4.3 (#14808) (Brandon Mills)
+* [`a96b05f`](https://github.com/eslint/eslint/commit/a96b05f6c5649cfee112d605c91d95aa191e2f78) Update: add end location to report in `consistent-return` (refs #12334) (#14798) (Nitin Kumar)
+* [`e0e8e30`](https://github.com/eslint/eslint/commit/e0e8e308929c9c66612505f2da89043f8592eea7) Docs: update BUG_REPORT template (#14787) (Nitin Kumar)
+* [`39115c8`](https://github.com/eslint/eslint/commit/39115c8b71d2629161359f6456f47fdbd552fddd) Docs: provide more context to no-eq-null (#14801) (gfyoung)
+* [`9a3c73c`](https://github.com/eslint/eslint/commit/9a3c73c130d437a65f4edba0dcb63390e68cac41) Docs: fix a broken link (#14790) (Sam Chen)
+* [`ddffa8a`](https://github.com/eslint/eslint/commit/ddffa8ad58b4b124b08061e9045fdb5370cbdbe3) Update: Indicating the operator in question (#14764) (Paul Smith)
+* [`bba714c`](https://github.com/eslint/eslint/commit/bba714c2ed813821ed288fbc07722cdde6e534fe) Update: Clarifying what changes need to be made in no-mixed-operators (#14765) (Paul Smith)
+* [`b0d22e3`](https://github.com/eslint/eslint/commit/b0d22e3eff18ea7f08189134c07cddceaec69a09) Docs: Mention benefit of providing `meta.docs.url` (#14774) (Bryan Mishkin)
+* [`000cc79`](https://github.com/eslint/eslint/commit/000cc796fd487e7b9ba8bcc5857dd691044479cc) Sponsors: Sync README with website (ESLint Jenkins)
+* [`a6a7438`](https://github.com/eslint/eslint/commit/a6a7438502abc6a1e29ec35cfbe2058ffc0803b1) Chore: pin fs-teardown@0.1.1 (#14771) (Milos Djermanovic)
+
 v7.30.0 - July 2, 2021
 
 * [`5f74642`](https://github.com/eslint/eslint/commit/5f746420700d457b92dd86659de588d272937b79) Chore: don't check Program.start in SourceCode#getComments (refs #14744) (#14748) (Milos Djermanovic)
diff --git a/Makefile.js b/Makefile.js
index 62b1d7666..6d1ee3919 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -197,7 +197,8 @@ function generateRuleIndexPage() {
                         name: basename,
                         description: rule.meta.docs.description,
                         recommended: rule.meta.docs.recommended || false,
-                        fixable: !!rule.meta.fixable
+                        fixable: !!rule.meta.fixable,
+                        hasSuggestions: !!rule.meta.docs.suggestion
                     },
                     category = categoriesData.categories.find(c => c.name === rule.meta.docs.category);
 
@@ -640,6 +641,7 @@ target.gensite = function(prereleaseVersion) {
 
     const RECOMMENDED_TEXT = "\n\n(recommended) The `\"extends\": \"eslint:recommended\"` property in a configuration file enables this rule.";
     const FIXABLE_TEXT = "\n\n(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.";
+    const HAS_SUGGESTIONS_TEXT = "\n\n(hasSuggestions) Some problems reported by this rule are manually fixable by editor [suggestions](../developer-guide/working-with-rules#providing-suggestions).";
 
     // 4. Loop through all files in temporary directory
     process.stdout.write("> Updating files (Steps 4-9): 0/... - ...\r");
@@ -669,13 +671,14 @@ target.gensite = function(prereleaseVersion) {
                 const rule = rules.get(ruleName);
                 const isRecommended = rule && rule.meta.docs.recommended;
                 const isFixable = rule && rule.meta.fixable;
+                const hasSuggestions = rule && rule.meta.docs.suggestion;
 
                 // Incorporate the special portion into the documentation content
                 const textSplit = text.split("\n");
                 const ruleHeading = textSplit[0];
                 const ruleDocsContent = textSplit.slice(1).join("\n");
 
-                text = `${ruleHeading}${isRecommended ? RECOMMENDED_TEXT : ""}${isFixable ? FIXABLE_TEXT : ""}\n${ruleDocsContent}`;
+                text = `${ruleHeading}${isRecommended ? RECOMMENDED_TEXT : ""}${isFixable ? FIXABLE_TEXT : ""}${hasSuggestions ? HAS_SUGGESTIONS_TEXT : ""}\n${ruleDocsContent}`;
                 title = `${ruleName} - Rules`;
 
                 if (rule && rule.meta) {
diff --git a/README.md b/README.md
index c87d07e0d..804310d8c 100644
--- a/README.md
+++ b/README.md
@@ -254,6 +254,16 @@ Toru Nagashima
 The people who review and fix bugs and help triage issues.
 
 <table><tbody><tr><td align="center" valign="top" width="11%">
+<a href="https://github.com/brettz9">
+<img src="https://github.com/brettz9.png?s=75" width="75" height="75"><br />
+Brett Zamir
+</a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/bmish">
+<img src="https://github.com/bmish.png?s=75" width="75" height="75"><br />
+Bryan Mishkin
+</a>
+</td><td align="center" valign="top" width="11%">
 <a href="https://github.com/g-plane">
 <img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
 Pig Fang
@@ -288,7 +298,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
 <p><a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://coinbase.com"><img src="https://avatars.githubusercontent.com/u/1885080?v=4" alt="Coinbase" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://retool.com/"><img src="https://images.opencollective.com/retool/98ea68e/logo.png" alt="Retool" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
+<p><a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.practiceignition.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/code-conventions.md b/docs/developer-guide/code-conventions.md
index 3ee02286c..0c1cbe624 100644
--- a/docs/developer-guide/code-conventions.md
+++ b/docs/developer-guide/code-conventions.md
@@ -1,925 +1,9 @@
 # Code Conventions
 
-Programming language style guides are important for the long-term maintainability of software. This guide is based on the [Code Conventions for the Java Programming Language](https://java.sun.com/docs/codeconv/) and [Douglas Crockford's Code Conventions for the JavaScript Programming Language](http://javascript.crockford.com/code.html). Modifications have been made due to my personal experience and preferences.
+Code conventions for ESLint are determined by
+[eslint-config-eslint](https://www.npmjs.com/package/eslint-config-eslint).
 
-## File Format
-
-Each file has this same basic format:
-
-```js
-/**
- * @fileoverview Description of the file
- * @author Your Name
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-// require() statements
-
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-// private methods/data
-
-//------------------------------------------------------------------------------
-// Public Interface
-//------------------------------------------------------------------------------
-
-// exported objects/methods
-module.exports = {
-
-};
-```
-
-The `@author` field gives you credit for having created the file.
-
-## Indentation
-
-Each indentation level is made up of four spaces. Do not use tabs.
-
-    // Good
-    if (true) {
-        doSomething();
-    }
-
-## Primitive Literals
-
-Strings should always use double quotes (never single quotes) and should always appear on a single line. Never use a slash to create a new line in a string.
-
-    // Good
-    var name = "Nicholas";
-
-    // Bad: Single quotes
-    var name = 'Nicholas';
-
-    // Bad: Wrapping to second line
-    var longString = "Here's the story, of a man \
-    named Brady.";
-
-Numbers should be written as decimal integers, e-notation integers, hexadecimal integers or floating-point decimals with at least one digit before and one digit after the decimal point. Never use octal literals.
-
-    // Good
-    var count = 10;
-
-    // Good
-    var price = 10.0;
-    var price = 10.00;
-
-    // Good
-    var num = 0xA2;
-
-    // Good
-    var num = 1e23;
-
-    // Bad: Hanging decimal point
-    var price = 10.;
-
-    // Bad: Leading decimal point
-    var price = .1;
-
-    // Bad: Octal (base 8) is deprecated
-    var num = 010;
-
-The special value `null` should be used only in the following situations:
-
-1. To initialize a variable that may later be assign an object value.
-1. To compare against an initialized variable that may or may not have an object value.
-1. To pass into a function where an object is expected.
-1. To return from a function where an object is expected.
-
-Examples:
-
-    // Good
-    var person = null;
-
-    // Good
-    function getPerson() {
-        if (condition) {
-            return new Person("Nicholas");
-        } else {
-            return null;
-        }
-    }
-
-    // Good
-    var person = getPerson();
-    if (person !== null){
-        doSomething();
-    }
-
-    // Bad: Testing against uninitialized variable
-    var person;
-    if (person != null){
-        doSomething();
-    }
-
-    // Bad: Testing to see if an argument was passed
-    function doSomething(arg1, arg2, arg3, arg4){
-        if (arg4 != null){
-            doSomethingElse();
-        }
-    }
-
-Never use the special value `undefined`. To see if a variable has been defined, use the `typeof` operator:
-
-    // Good
-    if (typeof variable == "undefined") {
-        // do something
-    }
-
-    // Bad: Using undefined literal
-    if (variable == undefined) {
-        // do something
-    }
-
-## Operator Spacing
-
-Operators with two operands must be preceded and followed by a single space to make the expression clear. Operators include assignments and logical operators.
-
-    // Good
-    var found = (values[i] === item);
-
-    // Good
-    if (found && (count > 10)) {
-        doSomething();
-    }
-
-    // Good
-    for (i = 0; i < count; i++) {
-        process(i);
-    }
-
-    // Bad: Missing spaces
-    var found = (values[i]===item);
-
-    // Bad: Missing spaces
-    if (found&&(count>10)) {
-        doSomething();
-    }
-
-    // Bad: Missing spaces
-    for (i=0; i<count; i++) {
-        process(i);
-    }
-
-## Parentheses Spacing
-
-When parentheses are used, there should be no whitespace immediately after the opening paren or immediately before the closing paren.
-
-    // Good
-    var found = (values[i] === item);
-
-    // Good
-    if (found && (count > 10)) {
-        doSomething();
-    }
-
-    // Good
-    for (i = 0; i < count; i++) {
-        process(i);
-    }
-
-    // Bad: Extra space after opening paren
-    var found = ( values[i] === item);
-
-    // Bad: Extra space before closing paren
-    if (found && (count > 10) ) {
-        doSomething();
-    }
-
-    // Bad: Extra space around argument
-    for (i = 0; i < count; i++) {
-        process( i );
-    }
-
-## Object Literals
-
-Object literals should have the following format:
-
-* The opening brace should be on the same line as the containing statement.
-* Each property-value pair should be indented one level with the first property appearing on the next line after the opening brace.
-* Each property-value pair should have an unquoted property name, followed by a colon (no space preceding it), followed by the value.
-* If the value is a function, it should wrap under the property name and should have a blank line both before and after the function.
-* Additional empty lines may be inserted to group related properties or otherwise improve readability.
-* The closing brace should be on a separate line.
-
-Examples:
-
-    // Good
-    var object = {
-
-        key1: value1,
-        key2: value2,
-
-        func: function() {
-            // do something
-        },
-
-        key3: value3
-    };
-
-    // Bad: Improper indentation
-    var object = {
-                    key1: value1,
-                    key2: value2
-                };
-
-    // Bad: Missing blank lines around function
-    var object = {
-
-        key1: value1,
-        key2: value2,
-        func: function() {
-            // do something
-        },
-        key3: value3
-    };
-
-When an object literal is passed to a function, the opening brace should be on the same line as if the value is a variable. All other formatting rules from above still apply.
-
-    // Good
-    doSomething({
-        key1: value1,
-        key2: value2
-    });
-
-    // Bad: All on one line
-    doSomething({ key1: value1, key2: value2 });
-
-## Comments
-
-Make frequent use of comments to aid others in understanding your code. Use comments when:
-
-* Code is difficult to understand.
-* The code might be mistaken for an error.
-* Browser-specific code is necessary but not obvious.
-* Documentation generation is necessary for an object, method, or property (use appropriate documentation comments).
-
-### Single-Line Comments
-
-Single-line comments should be used to document one line of code or a group of related lines of code. A single-line comment may be used in three ways:
-
-1. On a separate line, describing the code beneath it.
-1. At the end of a line, describing the code before it.
-1. On multiple lines, to comment out sections of code.
-
-When on a separate line, a single-line comment should be at the same indentation level as the code it describes and be preceded by a single line. Never use multiple single-line comments on consecutive lines, use a multi-line comment instead.
-
-    // Good
-    if (condition){
-
-        // if you made it here, then all security checks passed
-        allowed();
-    }
-
-    // Bad: No empty line preceding comment
-    if (condition){
-        // if you made it here, then all security checks passed
-        allowed();
-    }
-
-    // Bad: Wrong indentation
-    if (condition){
-
-    // if you made it here, then all security checks passed
-        allowed();
-    }
-
-    // Bad: This should be a multi-line comment
-    // This next piece of code is quite difficult, so let me explain.
-    // What you want to do is determine if the condition is true
-    // and only then allow the user in. The condition is calculated
-    // from several different functions and may change during the
-    // lifetime of the session.
-    if (condition){
-        // if you made it here, then all security checks passed
-        allowed();
-    }
-
-For single-line comments at the end of a line, ensure there is at least one indentation level between the end of the code and the beginning of the comment:
-
-    // Good
-    var result = something + somethingElse;    // somethingElse will never be null
-
-    // Bad: Not enough space between code and comment
-    var result = something + somethingElse;// somethingElse will never be null
-
-The only acceptable time to have multiple single-line comments on successive lines is to comment out large sections of code. Multi-line comments should not be used for this purpose.
-
-    // Good
-    // if (condition){
-    //    doSomething();
-    //    thenDoSomethingElse();
-    // }
-
-### Multi-Line Comments
-
-Multi-line comments should be used to document code that requires more explanation. Each multi-line comment should have at least three lines:
-
-1. The first line contains only the `/*` comment opening. No further text is allowed on this line.
-1. The next line(s) have a `*` aligned with the `*` in the first line. Text is allowed on these lines.
-1. The last line has the `*/` comment opening aligned with the preceding lines. No other text is allowed on this line.
-
-The first line of multi-comments should be indented to the same level as the code it describes. Each subsequent line should have the same indentation plus one space (for proper alignment of the `*` characters). Each multi-line comment should be preceded by one empty line.
-
-    // Good
-    if (condition){
-
-        /*
-         * if you made it here,
-         * then all security checks passed
-         */
-        allowed();
-    }
-
-    // Bad: No empty line preceding comment
-    if (condition){
-        /*
-         * if you made it here,
-         * then all security checks passed
-         */
-        allowed();
-    }
-
-    // Bad: Missing a space after asterisk
-    if (condition){
-
-        /*
-         *if you made it here,
-         *then all security checks passed
-         */
-        allowed();
-    }
-
-    // Bad: Wrong indentation
-    if (condition){
-
-    /*
-     * if you made it here,
-     * then all security checks passed
-     */
-        allowed();
-    }
-
-    // Bad: Don't use multi-line comments for trailing comments
-    var result = something + somethingElse;    /*somethingElse will never be null*/
-
-### Comment Annotations
-
-Comments may be used to annotate pieces of code with additional information. These annotations take the form of a single word followed by a colon. The acceptable annotations are:
-
-* `TODO` - indicates that the code is not yet complete. Information about the next steps should be included.
-* `HACK` - indicates that the code is using a shortcut. Information about why the hack is being used should be included. This may also indicate that it would be nice to come up with a better way to solve the problem.
-* `XXX` - indicates that the code is problematic and should be fixed as soon as possible.
-* `FIXME` - indicates that the code is problematic and should be fixed soon. Less important than `XXX`.
-* `REVIEW` - indicates that the code needs to be reviewed for potential changes.
-
-These annotations may be used with either single-line or multi-line comments and should follow the same formatting rules as the general comment type. Examples:
-
-    // Good
-    // TODO: I'd like to find a way to make this faster
-    doSomething();
-
-    // Good
-    /*
-     * HACK: Have to do this for IE. I plan on revisiting in
-     * the future when I have more time. This probably should
-     * get replaced before v1.2.
-     */
-    if (document.all) {
-        doSomething();
-    }
-
-    // Good
-    // REVIEW: Is there a better way to do this?
-    if (document.all) {
-        doSomething();
-    }
-
-    // Bad: Annotation spacing is incorrect
-    // TODO : I'd like to find a way to make this faster
-    doSomething();
-
-    // Bad: Comment should be at the same indentation as code
-        // REVIEW: Is there a better way to do this?
-    if (document.all) {
-        doSomething();
-    }
-
-
-## Variable Declarations
-
-All variables should be declared before they are used. Variable declarations should take place at the beginning of a function using a single `var` statement with one variable per line. All lines after the first should be indented one level so the variable names line up. Variables should be initialized when declared if applicable and the equals operator should be at a consistent indentation level. Initialized variables should come first followed by uninitialized variables.
-
-    // Good
-    var count   = 10,
-        name    = "Nicholas",
-        found   = false,
-        empty;
-
-    // Bad: Improper initialization alignment
-    var count = 10,
-        name = "Nicholas",
-        found= false,
-        empty;
-
-    // Bad: Incorrect indentation
-    var count   = 10,
-    name    = "Nicholas",
-    found   = false,
-    empty;
-
-    // Bad: Multiple declarations on one line
-    var count   = 10, name = "Nicholas",
-        found   = false, empty;
-
-    // Bad: Uninitialized variables first
-    var empty,
-        count   = 10,
-        name    = "Nicholas",
-        found   = false;
-
-    // Bad: Multiple var statements
-    var count   = 10,
-        name    = "Nicholas";
-
-    var found   = false,
-        empty;
-
-Always declare variables. Implied globals should not be used.
-
-## Function Declarations
-
-Functions should be declared before they are used. When a function is not a method (not attached to an object) it should be defined using function declaration format (not function expression format nor using the `Function` constructor). There should be no space between the function name and the opening parentheses. There should be one space between the closing parentheses and the right brace. The right brace should be on the same line as the `function` keyword. There should be no space after the opening parentheses or before the closing parentheses. Named arguments should have a space after the comma but not before it. The function body should be indented one level.
-
-    // Good
-    function doSomething(arg1, arg2) {
-        return arg1 + arg2;
-    }
-
-    // Bad: Improper spacing of first line
-    function doSomething (arg1, arg2){
-        return arg1 + arg2;
-    }
-
-    // Bad: Function expression
-    var doSomething = function(arg1, arg2) {
-        return arg1 + arg2;
-    };
-
-    // Bad: Left brace on wrong line
-    function doSomething(arg1, arg2)
-    {
-        return arg1 + arg2;
-    }
-
-    // Bad: Using Function constructor
-    var doSomething = new Function("arg1", "arg2", "return arg1 + arg2");
-
-Functions declared inside of other functions should be declared immediately after the `var` statement.
-
-    // Good
-    function outer() {
-
-        var count   = 10,
-            name    = "Nicholas",
-            found   = false,
-            empty;
-
-        function inner() {
-            // code
-        }
-
-        // code that uses inner()
-    }
-
-    // Bad: Inner function declared before variables
-    function outer() {
-
-        function inner() {
-            // code
-        }
-
-        var count   = 10,
-            name    = "Nicholas",
-            found   = false,
-            empty;
-
-        // code that uses inner()
-    }
-
-Anonymous functions may be used for assignment of object methods or as arguments to other functions. There should be no space between the `function` keyword and the opening parentheses.
-
-    // Good
-    object.method = function() {
-        // code
-    };
-
-    // Bad: Incorrect spacing
-    object.method = function () {
-        // code
-    };
-
-Immediately-invoked functions should surround the entire function call with parentheses.
-
-    // Good
-    var value = (function() {
-
-        // function body
-
-        return {
-            message: "Hi"
-        }
-    }());
-
-    // Bad: No parentheses around function call
-    var value = function() {
-
-        // function body
-
-        return {
-            message: "Hi"
-        }
-    }();
-
-    // Bad: Improper parentheses placement
-    var value = (function() {
-
-        // function body
-
-        return {
-            message: "Hi"
-        }
-    })();
-
-## Naming
-
-Care should be taken to name variables and functions properly. Names should be limited to alphanumeric characters and, in some cases, the underscore character. Do not use the dollar sign (`$`) or back slash (`\`) characters in any names.
-
-Variable names should be formatted in camel case with the first letter being lowercase and the first letter of each subsequent word being uppercase. The first word of a variable name should be a noun (not a verb) to avoid confusion with functions. Do not use underscore for variable names.
-
-    // Good
-    var accountNumber = "8401-1";
-
-    // Bad: Begins with uppercase letter
-    var AccountNumber = "8401-1";
-
-    // Bad: Begins with verb
-    var getAccountNumber = "8401-1";
-
-    // Bad: Uses underscore
-    var account_number = "8401-1";
-
-Function names should also be formatted using camel case. The first word of a function name should be a verb (not a noun) to avoid confusion with variables. Do not use underscore for function names.
-
-    // Good
-    function doSomething() {
-        // code
-    }
-
-    // Bad: Begins with uppercase letter
-    function DoSomething() {
-        // code
-    }
-
-    // Bad: Begins with noun
-    function car() {
-        // code
-    }
-
-    // Bad: Uses underscores
-    function do_something() {
-        // code
-    }
-
-Constructor functions, those functions used with the `new` operator to create new objects, should be formatted in camel case but must begin with an uppercase letter. Constructor function names should begin with a non-verb because `new` is the action of creating an object instance.
-
-    // Good
-    function MyObject() {
-        // code
-    }
-
-    // Bad: Begins with lowercase letter
-    function myObject() {
-        // code
-    }
-
-    // Bad: Uses underscores
-    function My_Object() {
-        // code
-    }
-
-    // Bad: Begins with verb
-    function getMyObject() {
-        // code
-    }
-
-Variables that act as constants (values that won't be changed) should be formatted using all uppercase letters with words separated by a single underscore.
-
-    // Good
-    var TOTAL_COUNT = 10;
-
-    // Bad: Camel case
-    var totalCount = 10;
-
-    // Bad: Mixed case
-    var total_COUNT = 10;
-
-Object properties follow the same naming conventions as variables. Object methods follow the same naming conventions as functions. If a property or method is meant to be private, then it should be prefixed with an underscore character.
-
-    // Good
-    var object = {
-        _count: 10,
-
-        _getCount: function () {
-            return this._count;
-        }
-    };
-
-## Strict Mode
-
-Strict mode should be used in all modules, specified below the file overview comment and above everything else:
-
-    // Bad: Strict mode in functions
-    function doSomething() {
-        "use strict";
-
-        // code
-    }
-
-    // Bad: Strict mode in global scope and redundant strict mode directive in function
-    "use strict";       // This one is good
-
-    function doSomething() {
-        "use strict";   // This one is bad
-
-        // code
-    }
-
-    // Good: Global strict mode
-    "use strict";
-
-    function doSomething() {
-        // no "use strict" here
-
-        // code
-    }
-
-## Assignments
-
-When assigning a value to a variable, use parentheses around a right-side expression that contains a comparison.
-
-    // Good
-    var flag = (i < count);
-
-    // Bad: Missing parentheses
-    var flag = i < count;
-
-## Equality Operators
-
-Use `===` and `!==` instead of `==` and `!=`. This avoids type coercion errors.
-
-    // Good
-    var same = (a === b);
-
-    // Bad: Using ==
-    var same = (a == b);
-
-## Ternary Operator
-
-The ternary operator should be used only for assigning values conditionally and never as a shortcut for an `if` statement.
-
-    // Good
-    var value = condition ? value1 : value2;
-
-    // Bad: no assignment, should be an if statement
-    condition ? doSomething() : doSomethingElse();
-
-## Statements
-
-### Simple Statements
-
-Each line should contain at most one statement. All simple statements should end with a semicolon (`;`).
-
-    // Good
-    count++;
-    a = b;
-
-    // Bad: Multiple statements on one line
-    count++; a = b;
-
-### return Statement
-
-A return statement with a value should not use parentheses unless they make the return value more obvious in some way. Example:
-
-    return;
-
-    return collection.size();
-
-    return (size > 0 ? size : defaultSize);
-
-### Compound Statements
-
-Compound statements are lists of statements enclosed inside of braces.
-
-* The enclosed statements should be indented one more level than the compound statement.
-* The opening brace should be at the end of the line that begins the compound statement; the closing brace should begin a line and be indented to the beginning of the compound statement.
-* Braces are used around all statements, even single statements, when they are part of a control structure, such as a `if` or `for` statement. This makes it easier to add statements without accidentally introducing bugs due to forgetting to add braces.
-* The statement beginning keyword, such as `if`, should be followed by one space and the opening brace should be preceded by a space.
-
-### if Statement
-
-The `if` class of statements should have the following form:
-
-    if (condition) {
-        statements
-    }
-
-    if (condition) {
-        statements
-    } else {
-        statements
-    }
-
-    if (condition) {
-        statements
-    } else if (condition) {
-        statements
-    } else {
-        statements
-    }
-
-It is never permissible to omit the braces in any part of an `if` statement.
-
-    // Good
-    if (condition) {
-        doSomething();
-    }
-
-    // Bad: Improper spacing
-    if(condition){
-        doSomething();
-    }
-
-    // Bad: Missing braces
-    if (condition)
-        doSomething();
-
-    // Bad: All on one line
-    if (condition) { doSomething(); }
-
-    // Bad: All on one line without braces
-    if (condition) doSomething();
-
-### for Statement
-
-The `for` class of statements should have the following form:
-
-    for (initialization; condition; update) {
-        statements
-    }
-
-    for (variable in object) {
-        statements
-    }
-
-Variables should not be declared in the initialization section of a `for` statement.
-
-    // Good
-    var i,
-        len;
-
-    for (i=0, len=10; i < len; i++) {
-        // code
-    }
-
-    // Bad: Variables declared during initialization
-    for (var i=0, len=10; i < len; i++) {
-        // code
-    }
-
-    // Bad: Variables declared during initialization
-    for (var prop in object) {
-        // code
-    }
-
-When using a `for-in` statement, double-check whether or not you need to use `hasOwnProperty()` to filter out object members.
-
-### while Statement
-
-The `while` class of statements should have the following form:
-
-    while (condition) {
-        statements
-    }
-
-### do Statement
-
-The `do` class of statements should have the following form:
-
-    do {
-        statements
-    } while (condition);
-
-Note the use of a semicolon as the final part of this statement. There should be a space before and after the `while` keyword.
-
-### switch Statement
-
-The `switch` class of statements should have the following form:
-
-    switch (expression) {
-        case expression:
-            statements
-
-        default:
-            statements
-    }
-
-Each `case` is indented one level under the `switch`. Each `case` after the first, including `default`, should be preceded by a single empty line.
-
-Each group of statements (except the default) should end with `break`, `return`, `throw`, or a comment indicating fall through.
-
-    // Good
-    switch (value) {
-        case 1:
-            /* falls through */
-
-        case 2:
-            doSomething();
-            break;
-
-        case 3:
-            return true;
-
-        default:
-            throw new Error("This shouldn't happen.);
-    }
-
-If a `switch` doesn't have a `default` case, then it should be indicated with a comment.
-
-    // Good
-    switch (value) {
-        case 1:
-            /*falls through*/
-
-        case 2:
-            doSomething();
-            break;
-
-        case 3:
-            return true;
-
-        // no default
-    }
-
-### try Statement
-
-The `try` class of statements should have the following form:
-
-    try {
-        statements
-    } catch (variable) {
-        statements
-    }
-
-    try {
-        statements
-    } catch (variable) {
-        statements
-    } finally {
-        statements
-    }
-
-## Whitespace
-
-Blank lines improve readability by setting off sections of code that are logically related.
-
-Two blank lines should always be used in the following circumstances:
-
-* Between sections of a source file
-* Between class and interface definitions
-
-One blank line should always be used in the following circumstances:
-
-* Between methods
-* Between the local variables in a method and its first statement
-* Before a multi-line or single-line comment
-* Between logical sections inside a method to improve readability
-
-Blank spaces should be used in the following circumstances:
-
-* A keyword followed by a parenthesis should be separated by a space.
-* A blank space should appear after commas in argument lists.
-* All binary operators except dot (`.`) should be separated from their operands by spaces. Blank spaces should never separate unary operators such as unary minus, increment (`++`), and decrement (`--`) from their operands.
-* The expressions in a `for` statement should be separated by blank spaces. Blank spaces should only be used after semicolons, not before.
-
-## Things to Avoid
-
-* Never use the primitive wrapper types, such as `String`, to create new objects.
-* Never use `eval()`.
-* Never use the `with` statement. This statement isn't available in strict mode and likely won't be available in future ECMAScript editions.
+The rationales for the specific rules in use can be found by looking to the
+project documentation for any given rule. If the rule is one of our own, see
+our own [rule documentation](https://eslint.org/docs/rules/) and otherwise, see
+the documentation of the plugin in which the rule can be found.
diff --git a/docs/developer-guide/nodejs-api.md b/docs/developer-guide/nodejs-api.md
index daa56e764..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>
@@ -462,7 +464,7 @@ const codeLines = SourceCode.splitLines(code);
 The `Linter` object does the actual evaluation of the JavaScript code. It doesn't do any filesystem operations, it simply parses and reports on the code. In particular, the `Linter` object does not process configuration objects or files.
 The `Linter` is a constructor, and you can create a new instance by passing in the options you want to use. The available options are:
 
-* `cwd` - Path to a directory that should be considered as the current working directory. It is accessible to rules by calling `context.getCwd()` (see [The Context Object](./working-with-rules.md#The-Context-Object)). If `cwd` is `undefined`, it will be normalized to `process.cwd()` if the global `process` object is defined (for example, in the Node.js runtime) , or `undefined` otherwise.
+* `cwd` - Path to a directory that should be considered as the current working directory. It is accessible to rules by calling `context.getCwd()` (see [The Context Object](./working-with-rules.md#the-context-object)). If `cwd` is `undefined`, it will be normalized to `process.cwd()` if the global `process` object is defined (for example, in the Node.js runtime) , or `undefined` otherwise.
 
 For example:
 
diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md
index c15f77c4c..77e05da10 100644
--- a/docs/developer-guide/working-with-rules.md
+++ b/docs/developer-guide/working-with-rules.md
@@ -61,7 +61,7 @@ The source file for a rule exports an object with the following properties.
     * `description` (string) provides the short description of the rule in the [rules index](../rules/)
     * `category` (string) specifies the heading under which the rule is listed in the [rules index](../rules/)
     * `recommended` (boolean) is whether the `"extends": "eslint:recommended"` property in a [configuration file](../user-guide/configuring/configuration-files.md#extending-configuration-files) enables the rule
-    * `url` (string) specifies the URL at which the full documentation can be accessed
+    * `url` (string) specifies the URL at which the full documentation can be accessed (enabling code editors to provide a helpful link on highlighted rule violations)
     * `suggestion` (boolean) specifies whether rules can return suggestions (defaults to false if omitted)
 
     In a custom rule or plugin, you can omit `docs` or include any properties that you need in it.
diff --git a/docs/rules/no-eq-null.md b/docs/rules/no-eq-null.md
index df8f97a5e..7b0f5df14 100644
--- a/docs/rules/no-eq-null.md
+++ b/docs/rules/no-eq-null.md
@@ -39,3 +39,11 @@ while (qux !== null) {
   baz();
 }
 ```
+
+## Compatibility
+
+* **JSHint**: This rule corresponds to `eqnull` rule of JSHint.
+
+## When Not To Use It
+
+If you want to enforce type-checking operations in general, use the more powerful [eqeqeq](./eqeqeq) instead.
diff --git a/docs/rules/space-after-keywords.md b/docs/rules/space-after-keywords.md
index af1b739fe..7f6182b22 100644
--- a/docs/rules/space-after-keywords.md
+++ b/docs/rules/space-after-keywords.md
@@ -2,7 +2,7 @@
 
 (removed) This rule was **removed** in ESLint v2.0 and replaced by the [keyword-spacing](keyword-spacing.md) rule.
 
-(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixed problems reported by this rule.
+(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#--fix) automatically fixed problems reported by this rule.
 
 Some style guides will require or disallow spaces following the certain keywords.
 
diff --git a/docs/rules/space-before-keywords.md b/docs/rules/space-before-keywords.md
index 8adf593a6..077c9a322 100644
--- a/docs/rules/space-before-keywords.md
+++ b/docs/rules/space-before-keywords.md
@@ -2,7 +2,7 @@
 
 (removed) This rule was **removed** in ESLint v2.0 and **replaced** by the [keyword-spacing](keyword-spacing.md) rule.
 
-(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixed problems reported by this rule.
+(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#--fix) automatically fixed problems reported by this rule.
 
 Keywords are syntax elements of JavaScript, such as `function` and `if`. These identifiers have special meaning to the language and so often appear in a different color in code editors. As an important part of the language, style guides often refer to the spacing that should be used around keywords. For example, you might have a style guide that says keywords should be always be preceded by spaces, which would mean `if-else` statements must look like this:
 
diff --git a/docs/rules/space-return-throw-case.md b/docs/rules/space-return-throw-case.md
index 024eb3c95..ff55f7f5e 100644
--- a/docs/rules/space-return-throw-case.md
+++ b/docs/rules/space-return-throw-case.md
@@ -2,7 +2,7 @@
 
 (removed) This rule was **removed** in ESLint v2.0 and **replaced** by the [keyword-spacing](keyword-spacing.md) rule.
 
-(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#fix) automatically fixed problems reported by this rule.
+(fixable) The `--fix` option on the [command line](../user-guide/command-line-interface#--fix) automatically fixed problems reported by this rule.
 
 Require spaces following `return`, `throw`, and `case`.
 
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/docs/user-guide/configuring/configuration-files.md b/docs/user-guide/configuring/configuration-files.md
index bf9b70d12..244fb0e98 100644
--- a/docs/user-guide/configuring/configuration-files.md
+++ b/docs/user-guide/configuring/configuration-files.md
@@ -297,7 +297,7 @@ The `extends` property value can be `"eslint:all"` to enable all core rules in t
 
 You might enable all core rules as a shortcut to explore rules and options while you decide on the configuration for a project, especially if you rarely override options or disable rules. The default options for rules are not endorsements by ESLint (for example, the default option for the [`quotes`](https://eslint.org/docs/rules/quotes) rule does not mean double quotes are better than single quotes).
 
-If your configuration extends `eslint:all`, after you upgrade to a newer major or minor version of ESLint, review the reported problems before you use the `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fix), so you know if a new fixable rule will make changes to the code.
+If your configuration extends `eslint:all`, after you upgrade to a newer major or minor version of ESLint, review the reported problems before you use the `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#--fix), so you know if a new fixable rule will make changes to the code.
 
 Example of a configuration file in JavaScript format:
 
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/consistent-return.js b/lib/rules/consistent-return.js
index a250430cb..0e20209af 100644
--- a/lib/rules/consistent-return.js
+++ b/lib/rules/consistent-return.js
@@ -104,18 +104,18 @@ module.exports = {
             } else if (node.type === "ArrowFunctionExpression") {
 
                 // `=>` token
-                loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc.start;
+                loc = context.getSourceCode().getTokenBefore(node.body, astUtils.isArrowToken).loc;
             } else if (
                 node.parent.type === "MethodDefinition" ||
                 (node.parent.type === "Property" && node.parent.method)
             ) {
 
                 // Method name.
-                loc = node.parent.key.loc.start;
+                loc = node.parent.key.loc;
             } else {
 
                 // Function name or `function` keyword.
-                loc = (node.id || node).loc.start;
+                loc = (node.id || context.getSourceCode().getFirstToken(node)).loc;
             }
 
             if (!name) {
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/lib/rules/no-mixed-operators.js b/lib/rules/no-mixed-operators.js
index 15eb20bed..5a2e139a6 100644
--- a/lib/rules/no-mixed-operators.js
+++ b/lib/rules/no-mixed-operators.js
@@ -117,7 +117,7 @@ module.exports = {
         ],
 
         messages: {
-            unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'."
+            unexpectedMixedOperator: "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'. Use parentheses to clarify the intended order of operations."
         }
     },
 
diff --git a/lib/rules/operator-assignment.js b/lib/rules/operator-assignment.js
index fdb088492..a48d27251 100644
--- a/lib/rules/operator-assignment.js
+++ b/lib/rules/operator-assignment.js
@@ -76,8 +76,8 @@ module.exports = {
 
         fixable: "code",
         messages: {
-            replaced: "Assignment can be replaced with operator assignment.",
-            unexpected: "Unexpected operator assignment shorthand."
+            replaced: "Assignment (=) can be replaced with operator assignment ({{operator}}=).",
+            unexpected: "Unexpected operator assignment ({{operator}}=) shorthand."
         }
     },
 
@@ -113,6 +113,7 @@ module.exports = {
                     context.report({
                         node,
                         messageId: "replaced",
+                        data: { operator },
                         fix(fixer) {
                             if (canBeFixed(left) && canBeFixed(expr.left)) {
                                 const equalsToken = getOperatorToken(node);
@@ -139,7 +140,8 @@ module.exports = {
                      */
                     context.report({
                         node,
-                        messageId: "replaced"
+                        messageId: "replaced",
+                        data: { operator }
                     });
                 }
             }
@@ -155,6 +157,7 @@ module.exports = {
                 context.report({
                     node,
                     messageId: "unexpected",
+                    data: { operator: node.operator },
                     fix(fixer) {
                         if (canBeFixed(node.left)) {
                             const firstToken = sourceCode.getFirstToken(node);
diff --git a/package.json b/package.json
index ac3a78cc3..ea08a90ef 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "7.30.0",
+  "version": "7.31.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -44,7 +44,7 @@
   "bugs": "https://github.com/eslint/eslint/issues/",
   "dependencies": {
     "@babel/code-frame": "7.12.11",
-    "@eslint/eslintrc": "^0.4.2",
+    "@eslint/eslintrc": "^0.4.3",
     "@humanwhocodes/config-array": "^0.5.0",
     "ajv": "^6.10.0",
     "chalk": "^4.0.0",
@@ -96,14 +96,14 @@
     "ejs": "^3.0.2",
     "eslint": "file:.",
     "eslint-config-eslint": "file:packages/eslint-config-eslint",
-    "eslint-plugin-eslint-plugin": "^3.2.0",
+    "eslint-plugin-eslint-plugin": "^3.4.0",
     "eslint-plugin-internal-rules": "file:tools/internal-rules",
     "eslint-plugin-jsdoc": "^25.4.3",
     "eslint-plugin-node": "^11.1.0",
     "eslint-release": "^2.0.0",
     "eslump": "^3.0.0",
     "esprima": "^4.0.1",
-    "fs-teardown": "^0.1.0",
+    "fs-teardown": "0.1.1",
     "glob": "^7.1.6",
     "jsdoc": "^3.5.5",
     "karma": "^6.1.1",
diff --git a/tools/internal-rules/consistent-docs-url.js b/tools/internal-rules/consistent-docs-url.js
deleted file mode 100644
index 052fe55f2..000000000
--- a/tools/internal-rules/consistent-docs-url.js
+++ /dev/null
@@ -1,119 +0,0 @@
-/**
- * @fileoverview Internal rule to enforce meta.docs.url conventions.
- * @author Patrick McElhaney
- */
-
-"use strict";
-
-const path = require("path");
-
-//------------------------------------------------------------------------------
-// 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;
-
-    if (!Array.isArray(properties)) {
-
-        // if properties is not an array, "internal-no-invalid-meta" will already report this.
-        return null;
-    }
-
-    for (let i = 0; i < properties.length; i++) {
-        if (properties[i].key.name === property) {
-            return properties[i];
-        }
-    }
-
-    return null;
-}
-
-/**
- * Verifies that the meta.docs.url property is present and has the correct value.
- * @param {RuleContext} context The ESLint rule context.
- * @param {ASTNode} exportsNode ObjectExpression node that the rule exports.
- * @returns {void}
- */
-function checkMetaDocsUrl(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 metaDocs = metaProperty && getPropertyFromObject("docs", metaProperty.value);
-    const metaDocsUrl = metaDocs && getPropertyFromObject("url", metaDocs.value);
-
-    if (!metaDocs) {
-        context.report({
-            node: metaProperty,
-            messageId: "missingMetaDocs"
-        });
-        return;
-    }
-
-    if (!metaDocsUrl) {
-        context.report({
-            node: metaDocs,
-            messageId: "missingMetaDocsUrl"
-        });
-        return;
-    }
-
-    const ruleId = path.basename(context.getFilename().replace(/.js$/u, ""));
-    const expected = `https://eslint.org/docs/rules/${ruleId}`;
-    const url = metaDocsUrl.value.value;
-
-    if (url !== expected) {
-        context.report({
-            node: metaDocsUrl.value,
-            messageId: "incorrectUrl",
-            data: { expected, url }
-        });
-    }
-
-}
-
-//------------------------------------------------------------------------------
-// Rule Definition
-//------------------------------------------------------------------------------
-
-module.exports = {
-    meta: {
-        docs: {
-            description: "enforce correct conventions of `meta.docs.url` property in core rules",
-            category: "Internal",
-            recommended: false
-        },
-        type: "suggestion",
-        schema: [],
-        messages: {
-            missingMetaDocs: "Rule is missing a meta.docs property.",
-            missingMetaDocsUrl: "Rule is missing a meta.docs.url property.",
-            incorrectUrl: 'Incorrect url. Expected "{{ expected }}" but got "{{ url }}".'
-        }
-    },
-
-    create(context) {
-        return {
-            AssignmentExpression(node) {
-                if (node.left &&
-                    node.right &&
-                    node.left.type === "MemberExpression" &&
-                    node.left.object.name === "module" &&
-                    node.left.property.name === "exports") {
-
-                    checkMetaDocsUrl(context, node.right);
-                }
-            }
-        };
-    }
-};
diff --git a/tools/internal-rules/no-invalid-meta.js b/tools/internal-rules/no-invalid-meta.js
index e5a74b359..69b43d4c8 100644
--- a/tools/internal-rules/no-invalid-meta.js
+++ b/tools/internal-rules/no-invalid-meta.js
@@ -50,17 +50,6 @@ function hasMetaDocs(metaPropertyNode) {
     return Boolean(getPropertyFromObject("docs", metaPropertyNode.value));
 }
 
-/**
- * Whether this `meta` ObjectExpression has a `docs.description` property defined or not.
- * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
- * @returns {boolean} `true` if a `docs.description` property exists.
- */
-function hasMetaDocsDescription(metaPropertyNode) {
-    const metaDocs = getPropertyFromObject("docs", metaPropertyNode.value);
-
-    return metaDocs && getPropertyFromObject("description", metaDocs.value);
-}
-
 /**
  * Whether this `meta` ObjectExpression has a `docs.category` property defined or not.
  * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
@@ -83,15 +72,6 @@ function hasMetaDocsRecommended(metaPropertyNode) {
     return metaDocs && getPropertyFromObject("recommended", metaDocs.value);
 }
 
-/**
- * Whether this `meta` ObjectExpression has a `schema` property defined or not.
- * @param {ASTNode} metaPropertyNode The `meta` ObjectExpression for this rule.
- * @returns {boolean} `true` if a `schema` property exists.
- */
-function hasMetaSchema(metaPropertyNode) {
-    return getPropertyFromObject("schema", metaPropertyNode.value);
-}
-
 /**
  * Checks the validity of the meta definition of this rule and reports any errors found.
  * @param {RuleContext} context The ESLint rule context.
@@ -111,11 +91,6 @@ function checkMetaValidity(context, exportsNode) {
         return;
     }
 
-    if (!hasMetaDocsDescription(metaProperty)) {
-        context.report({ node: metaProperty, messageId: "missingMetaDocsDescription" });
-        return;
-    }
-
     if (!hasMetaDocsCategory(metaProperty)) {
         context.report({ node: metaProperty, messageId: "missingMetaDocsCategory" });
         return;
@@ -123,23 +98,9 @@ function checkMetaValidity(context, exportsNode) {
 
     if (!hasMetaDocsRecommended(metaProperty)) {
         context.report({ node: metaProperty, messageId: "missingMetaDocsRecommended" });
-        return;
-    }
-
-    if (!hasMetaSchema(metaProperty)) {
-        context.report({ node: metaProperty, messageId: "missingMetaSchema" });
     }
 }
 
-/**
- * Whether this node is the correct format for a rule definition or not.
- * @param {ASTNode} node node that the rule exports.
- * @returns {boolean} `true` if the exported node is the correct format for a rule definition
- */
-function isCorrectExportsFormat(node) {
-    return node.type === "ObjectExpression";
-}
-
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -156,12 +117,9 @@ module.exports = {
         messages: {
             missingMeta: "Rule is missing a meta property.",
             missingMetaDocs: "Rule is missing a meta.docs property.",
-            missingMetaDocsDescription: "Rule is missing a meta.docs.description property.",
             missingMetaDocsCategory: "Rule is missing a meta.docs.category property.",
             missingMetaDocsRecommended: "Rule is missing a meta.docs.recommended property.",
-            missingMetaSchema: "Rule is missing a meta.schema property.",
-            noExport: "Rule does not export anything. Make sure rule exports an object according to new rule format.",
-            incorrectExport: "Rule does not export an Object. Make sure the rule follows the new rule format."
+            noExport: "Rule does not export anything. Make sure rule exports an object according to new rule format."
         }
     },
 
@@ -186,11 +144,6 @@ module.exports = {
                         node,
                         messageId: "noExport"
                     });
-                } else if (!isCorrectExportsFormat(exportsNode)) {
-                    context.report({
-                        node: exportsNode,
-                        messageId: "incorrectExport"
-                    });
                 } else {
                     checkMetaValidity(context, exportsNode);
                 }


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/consistent-return.js b/tests/lib/rules/consistent-return.js
index 53781ea42..16a1ed97a 100644
--- a/tests/lib/rules/consistent-return.js
+++ b/tests/lib/rules/consistent-return.js
@@ -52,7 +52,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "missingReturnValue",
                     data: { name: "Function 'foo'" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 46,
+                    endLine: 1,
+                    endColumn: 53
                 }
             ]
         },
@@ -63,7 +67,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "missingReturnValue",
                     data: { name: "Arrow function" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 47,
+                    endLine: 1,
+                    endColumn: 54
                 }
             ]
         },
@@ -73,7 +81,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "unexpectedReturnValue",
                     data: { name: "Function 'foo'" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 41,
+                    endLine: 1,
+                    endColumn: 54
                 }
             ]
         },
@@ -83,7 +95,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "missingReturnValue",
                     data: { name: "Function" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 44,
+                    endLine: 1,
+                    endColumn: 51
                 }
             ]
         },
@@ -93,7 +109,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "unexpectedReturnValue",
                     data: { name: "Function" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 39,
+                    endLine: 1,
+                    endColumn: 52
                 }
             ]
         },
@@ -104,7 +124,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "unexpectedReturnValue",
                     data: { name: "Arrow function" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 33,
+                    endLine: 1,
+                    endColumn: 46
                 }
             ]
         },
@@ -116,7 +140,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturnValue",
                     data: { name: "Function 'foo'" },
                     type: "ReturnStatement",
-                    column: 41
+                    line: 1,
+                    column: 41,
+                    endLine: 1,
+                    endColumn: 58
                 }
             ]
         },
@@ -128,7 +155,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturnValue",
                     data: { name: "Function 'foo'" },
                     type: "ReturnStatement",
-                    column: 41
+                    line: 1,
+                    column: 41,
+                    endLine: 1,
+                    endColumn: 55
                 }
             ]
         },
@@ -140,7 +170,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "unexpectedReturnValue",
                     data: { name: "Function 'foo'" },
                     type: "ReturnStatement",
-                    column: 46
+                    line: 1,
+                    column: 46,
+                    endLine: 1,
+                    endColumn: 58
                 }
             ]
         },
@@ -152,7 +185,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "unexpectedReturnValue",
                     data: { name: "Function 'foo'" },
                     type: "ReturnStatement",
-                    column: 43
+                    line: 1,
+                    column: 43,
+                    endLine: 1,
+                    endColumn: 55
                 }
             ]
         },
@@ -163,7 +199,11 @@ ruleTester.run("consistent-return", rule, {
                 {
                     messageId: "missingReturnValue",
                     data: { name: "Program" },
-                    type: "ReturnStatement"
+                    type: "ReturnStatement",
+                    line: 1,
+                    column: 25,
+                    endLine: 1,
+                    endColumn: 32
                 }
             ]
         },
@@ -174,7 +214,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "function 'foo'" },
                     type: "FunctionDeclaration",
-                    column: 10
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -185,7 +228,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "function '_foo'" },
                     type: "FunctionDeclaration",
-                    column: 10
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 14
                 }
             ]
         },
@@ -196,7 +242,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "function 'foo'" },
                     type: "FunctionExpression",
-                    column: 12
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         },
@@ -207,7 +256,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "function" },
                     type: "FunctionExpression",
-                    column: 3
+                    line: 1,
+                    column: 3,
+                    endLine: 1,
+                    endColumn: 11
                 }
             ]
         },
@@ -219,7 +271,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "arrow function" },
                     type: "ArrowFunctionExpression",
-                    column: 6
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 8
                 }
             ]
         },
@@ -231,7 +286,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "method 'foo'" },
                     type: "FunctionExpression",
-                    column: 12
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         },
@@ -243,7 +301,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "method 'foo'" },
                     type: "FunctionExpression",
-                    column: 10
+                    line: 1,
+                    column: 10,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -255,7 +316,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "program" },
                     type: "Program",
-                    column: 1
+                    line: 1,
+                    column: 1,
+                    endLine: void 0,
+                    endColumn: void 0
                 }
             ]
         },
@@ -267,7 +331,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "method 'CapitalizedFunction'" },
                     type: "FunctionExpression",
-                    column: 11
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 30
                 }
             ]
         },
@@ -279,7 +346,10 @@ ruleTester.run("consistent-return", rule, {
                     messageId: "missingReturn",
                     data: { name: "method 'constructor'" },
                     type: "FunctionExpression",
-                    column: 4
+                    line: 1,
+                    column: 4,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         }
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/lib/rules/unicode-bom.js b/tests/lib/rules/unicode-bom.js
index 0b94a6902..62abee698 100644
--- a/tests/lib/rules/unicode-bom.js
+++ b/tests/lib/rules/unicode-bom.js
@@ -41,24 +41,52 @@ ruleTester.run("unicode-bom", rule, {
             code: "var a = 123;",
             output: "\uFEFFvar a = 123;",
             options: ["always"],
-            errors: [expectedError]
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 1,
+                endLine: void 0,
+                endColumn: void 0
+
+            }]
         },
         {
             code: " // here's a comment \nvar a = 123;",
             output: "\uFEFF // here's a comment \nvar a = 123;",
             options: ["always"],
-            errors: [expectedError]
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 1,
+                endLine: void 0,
+                endColumn: void 0
+
+            }]
         },
         {
             code: "\uFEFF var a = 123;",
             output: " var a = 123;",
-            errors: [unexpectedError]
+            errors: [{
+                ...unexpectedError,
+                line: 1,
+                column: 1,
+                endLine: void 0,
+                endColumn: void 0
+
+            }]
         },
         {
             code: "\uFEFF var a = 123;",
             output: " var a = 123;",
             options: ["never"],
-            errors: [unexpectedError]
+            errors: [{
+                ...unexpectedError,
+                line: 1,
+                column: 1,
+                endLine: void 0,
+                endColumn: void 0
+
+            }]
         }
     ]
 });
diff --git a/tests/tools/internal-rules/consistent-docs-url.js b/tests/tools/internal-rules/consistent-docs-url.js
deleted file mode 100644
index 4b3d3a05b..000000000
--- a/tests/tools/internal-rules/consistent-docs-url.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * @fileoverview Tests for internal-consistent-docs-url rule.
- * @author Patrick McElhaney
- */
-
-"use strict";
-
-//------------------------------------------------------------------------------
-// Requirements
-//------------------------------------------------------------------------------
-
-const rule = require("../../../tools/internal-rules/consistent-docs-url"),
-    { RuleTester } = require("../../../lib/rule-tester");
-
-//------------------------------------------------------------------------------
-// Tests
-//------------------------------------------------------------------------------
-
-const ruleTester = new RuleTester();
-
-ruleTester.run("consistent-docs-url", rule, {
-    valid: [
-
-        // wrong exports format: "internal-no-invalid-meta" reports this already
-        [
-            "module.exports = function(context) {",
-            "    return {",
-            "        Program: function(node) {}",
-            "    };",
-            "};"
-        ].join("\n"),
-        [
-            "module.exports = {",
-            "    meta: {",
-            "        docs: {",
-            "            url: 'https://eslint.org/docs/rules/<input>'",
-            "        }",
-            "    },",
-            "    create: function(context) {",
-            "        return {};",
-            "    }",
-            "};"
-        ].join("\n")
-    ],
-    invalid: [
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "    },",
-
-                "    create: function(context) {",
-                "        return {};",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "missingMetaDocs",
-                line: 2,
-                column: 5
-            }]
-        },
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "        docs: {}",
-                "    },",
-
-                "    create: function(context) {",
-                "        return {};",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "missingMetaDocsUrl",
-                line: 3,
-                column: 9
-            }]
-        },
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "        docs: {",
-                "            url: 'http://example.com/wrong-url'",
-                "        }",
-                "    },",
-                "    create: function(context) {",
-                "        return {};",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "incorrectUrl",
-                data: {
-                    expected: "https://eslint.org/docs/rules/<input>",
-                    url: "http://example.com/wrong-url"
-                },
-                line: 4,
-                column: 18
-            }]
-        }
-    ]
-});
diff --git a/tests/tools/internal-rules/no-invalid-meta.js b/tests/tools/internal-rules/no-invalid-meta.js
index a5ff4d55a..6db173a15 100644
--- a/tests/tools/internal-rules/no-invalid-meta.js
+++ b/tests/tools/internal-rules/no-invalid-meta.js
@@ -96,20 +96,6 @@ ruleTester.run("no-invalid-meta", rule, {
         ].join("\n")
     ],
     invalid: [
-        {
-            code: [
-                "module.exports = function(context) {",
-                "    return {",
-                "        Program: function(node) {}",
-                "    };",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "incorrectExport",
-                line: 1,
-                column: 18
-            }]
-        },
         {
             code: [
                 "module.exports = {",
@@ -164,30 +150,6 @@ ruleTester.run("no-invalid-meta", rule, {
                 column: 5
             }]
         },
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "        docs: {",
-                "            category: 'Internal',",
-                "            recommended: false",
-                "        },",
-                "        schema: []",
-                "    },",
-
-                "    create: function(context) {",
-                "        return {",
-                "            Program: function(node) {}",
-                "        };",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "missingMetaDocsDescription",
-                line: 2,
-                column: 5
-            }]
-        },
         {
             code: [
                 "module.exports = {",
@@ -236,30 +198,6 @@ ruleTester.run("no-invalid-meta", rule, {
                 column: 5
             }]
         },
-        {
-            code: [
-                "module.exports = {",
-                "    meta: {",
-                "        docs: {",
-                "            description: 'some rule',",
-                "            category: 'Internal',",
-                "            recommended: false",
-                "        }",
-                "    },",
-
-                "    create: function(context) {",
-                "        return {",
-                "            Program: function(node) {}",
-                "        };",
-                "    }",
-                "};"
-            ].join("\n"),
-            errors: [{
-                messageId: "missingMetaSchema",
-                line: 2,
-                column: 5
-            }]
-        },
         {
             code: "",
             errors: [{