Repository: eslint/eslint
Pull request #12556 (2019-11-11 13:50:11)

New: Add offsetTernaryExpressions option for indent rule
**What is the purpose of this pull request?**

Adds `offsetTernaryExpressions` boolean indent rule that solves following issues:
- https://github.com/eslint/eslint/issues/6606
- https://github.com/eslint/eslint/issues/7698
- https://github.com/standard/standard/issues/927
- https://github.com/standard/standard/issues/1451
- https://github.com/sheerun/prettier-standard/issues/76
- https://github.com/brodybits/prettierx/issues/41

**Please describe what the rule should do:**

Functions are normally formatted with indentation which looks nice:

```es6
commission => {
  return suggestions.hits.map(hit => something(hit))
}
```

but when ternary expression is used suddenly `return` is at the same level as argument:

```es6
search.premium
  ? commission => {
    return suggestions.hits.map(hit => something(hit))
  }
  : () => onOpen()
```

This is just one example of many of issues described in referenced github issues, that is: the values of ternary expression are indented at the same level as `?` and `:` instead of having its own indent level.

Here's an example with multi-level `?:`. That's how it is currently:

```es6
search.premium
  ? commission => {
    return suggestions.hits.map(hit => something(hit))
  }
  : something
    ? commission => {
      return suggestions.hits.map(hit => something(hit))
    }
    : null
```

And that's what many developers are expecting:

```es6
search.premium
  ? commission => {
      return suggestions.hits.map(hit => something(hit))
    }
  : something
    ? commission => {
        return suggestions.hits.map(hit => something(hit))
      }
    : null
```

Ternary expressions are very often used in JSX so this this issue is especially annoying. For example this is how this rule formats code currently:

```jsx
const Component = () => (
  <ul className='has-text-centered'>
    {landmarks.hits.length > 0
      ? landmarks.hits.map(({ name, objectID }) => (
        <li key={name}>
          <a href={`${process.env.DOMAIN}` + `/city/${objectID}`}>{name}</a>
        </li>
      ))
      : null}
  </ul>
)
```

And that's what many developers are expecting:

```jsx
const Component = () => (
  <ul className='has-text-centered'>
    {landmarks.hits.length > 0
      ? landmarks.hits.map(({ name, objectID }) => (
          <li key={name}>
            <a href={`${process.env.DOMAIN}` + `/city/${objectID}`}>{name}</a>
          </li>
        ))
      : null}
  </ul>
)
```
I get that it's not possible to make this rule a default, so I'm introducing `offsetTernaryExpressions` rules that allows to fix the number of issues above.

Actually this rule also makes it possible to indent ternary expressions similarly to how prettier does it. Here is multiline ternary expression as formatted by prettier:

```jsx
search.premium
  ? commission => {
      return suggestions.hits.map(hit => something(hit))
    }
  : something
  ? commission => {
      return suggestions.hits.map(hit => something(hit))
    }
  : null
```

Please note that prettier is putting `?:` at the same level as nested `?:`, but this rule is very separate from properly indenting `commission => { ... }` expressions.

**What category of rule is this? (place an "X" next to just one item)**

[X] Enforces code style
[ ] Warns about a potential error
[ ] Suggests an alternate way of doing something
[ ] Other (please specify:)

**Provide 2-3 code examples that this rule will warn about:**

```es6
search.premium
  ? commission => {
    return suggestions.hits.map(hit => something(hit))
  }
  : () => onOpen()
```

```es6
const object = cond
  ? {
    foo: 'bar'
  }
  : {
    baz: 'qux'
  }
```

**Why should this rule be included in ESLint (instead of a plugin)?**

Enforcing indentation is deeply integrated into eslint. It's not efficient to do it in plugin.

**What changes did you make? (Give an overview)**

- Add boolean `offsetTernaryExpressions` rules that enforces the style described above
- Add tests and documentation for it


jsf-clabot: [![CLA assistant check](https://cla.js.foundation/pull/badge/not_signed)](https://cla.js.foundation/eslint/eslint?pullRequest=12556) <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint?pullRequest=12556) before we can accept your contribution.<br/>
sheerun: I've fixed some of the examples I've described in description of this issue
Janpot: @sheerun 

> And that's what many developers are expecting:

When I look at jsx rules in `standard`, it already fails on:

```jsx
condition
  ? <x>
    y
  </x>
  : null
```
with
```
 Expected closing tag to match indentation of opening. (react/jsx-closing-tag-location)
```
Trying to correct it by doing
```jsx
condition
  ? <x>
      y
    </x>
  : null
```
fails with
```
Expected indentation of 4 spaces but found 6.
```
The only way (that I know of) to satisfy `standard` is by doing
```jsx
condition
  ? (
    <x>
      y
    </x>
  )
  : null
```

Now, it seems to me that the case presented in this PR is quite analog to the jsx one. And it seems to me that in that case, the expectation would be to format it as:
```js
search.premium
  ? (
    commission => {
      return suggestions.hits.map(hit => something(hit))
    }
  )
  : (
    something
      ? (
        commission => {
          return suggestions.hits.map(hit => something(hit))
        }
      )
      : null
  )
```
Ofcourse, that is unless the jsx behavior was unintend, or unless consistency between these two variants of ternary is not of importance. Personally I'd argue it is important, and I'd argue the behavior I present here is the desired on.
sheerun: @Janpot It seems that this PR would fix your issue as well, because:

```es6
condition
  ? <x>
      y
    </x>
  : null
```

doesn't return any errors when `"offsetTernaryExpressions": true` is used

As for your last example this PR would format it as:

```es6
search.premium
  ? (
      commission => {
        return suggestions.hits.map(hit => something(hit))
      }
    )
  : (
      something
        ? (
            commission => {
              return suggestions.hits.map(hit => something(hit))
            }
          )
        : null
    )
```

but the parenthesis are not necessary, and without them it formats it more nicely:

```es6
search.premium
  ? commission => {
      return suggestions.hits.map(hit => something(hit))
    }
  : something
    ? commission => {
        return suggestions.hits.map(hit => something(hit))
      }
    : null
```
Janpot: OK, seems like "unless the jsx behavior was unintend" applies here. LGTM then 👍 
Janpot: @sheerun How would this work with indentation !== 2 spaces? What in case of > 2 spaces? What if tabs are used?
sheerun: @Janpot This style is not really compatible with 4-spaces indentation, because it would introduce 6-spaces indentation or 10-spaces indentation in many places...

Here's example:

```es6
search.premium
    ? commission => { // 4 spaces
          return suggestions.hits.map(hit => something(hit)) // 10 spaces?
      } // 6 spaces?
    : something
```

alternative:

```es6
search.premium
    ?   commission => { // 4 spaces + 2 spaces?
            return suggestions.hits.map(hit => something(hit)) // 12 spaces
        } // 8 spaces
    :   something // what?
```
josephfrazier: Given the popularity of 2-space indentation, what if we made it so that this option only applies if you also have 2-space indentation? Either that, or just trust that people without 2-space indentation won't use this option unless they're ok with the output
ljharb: @josephfrazier 2-space, 4-space, and tabs are all popular enough that they all should be considered.
sheerun: @ljharb I'm indifferent what happens if 4-spaces and tabs are used. Can you suggest what the formatting should be that eslint is going to accept? Best by example.
ljharb: @sheerun
correct code:
```js
 /*eslint indent: ["error", 4, { "offsetTernaryExpressions": true }]*/

condition
    ? () => {
            return true
        }
    : condition2
     ? () => {
            return true
        }
     : () => {
            return false
        }
 ```

```js
 /*eslint indent: ["error", 'tab', { "offsetTernaryExpressions": true }]*/

condition
	? () => {
			return true
		}
	: condition2
	? () => {
			return true
		}
	: () => {
			return false
		}
 ```

(the tabs example will ofc look horrible at the default 8-space width, but a) that's the whole point of tabs - their width is configurable, so you're not oppressed into someone else's preferred width, and b) everyone uses a 2-space or 4-space width for their tabs anyways.
sheerun: @ljharb I don't get you examples in some places. They deviate very much from "basic" eslint indentation rules so fixing them your way would require a lot of code and hacks. In particular nested `?:` should be indented by 4 spaces and all indentation should be multiply of 4 spaces. Could you explain each comment with question mark at the end?

```es6
 /*eslint indent: ["error", 4, { "offsetTernaryExpressions": true }]*/

condition
    ? () => {
            return true // 12 spaces
        } // 8 spaces
    : condition2
     ? () => { // 7 spaces?
            return true // again 12 spaces even though nested ternary is indented? 
        } // again 8 spaces even though ternary is nested?
     : () => { // again 12 spaces even though ternary is nested?
            return false // again 8 spaces even though nested ternary is indented? 
        }
```

```es6
condition
	? () => {
			return true
		}
	: condition2
	? () => { // why ? is at the same level? 
			return true
		}
	: () => {
			return false
		}
```


My suggestion is to use following for 4-spaces indent that is consistent:

```es6
condition
    ? () => { // 4 spaces
            return true // 12 spaces
        } // 8 spaces
    : condition2 // 4 spaces
        ? () => { // 8 spaces
                return true // 16 spaces
            } // 12 spaces
        : () => { // 8 spaces
                return false // 16 spaces
            } // 12 spaces
```

As you can see this makes number of spaces everywhere a multiply of 4 and makes indentation with tabs + nested indentation for `?:` possible.
ljharb: @sheerun the 7 spaces is a mistake :-) all i did is take your 2-space example, and attempt to double the number of spaces; and then take it again and convert each 2-space to a `\t`.

Indentation rules should deal in indentation "levels" - i should be able to set it to 57 spaces, and 3 indentation levels thus produces 171 spaces; or 1 space, and thus 3 spaces. The number or "tab" shouldn't impact how the rules work, just which character(s) represent "one indentation level".
sheerun: @ljharb According to what you're saying my last example should be correct one, correct? And here's additional correct example with tabs:

```es6
condition
	? () => { // 1 tab
			return true // 3 tabs
		} // 2 tabs
	: condition2 // 1 tab
		? () => { // 2 tabs
				return true // 4 tabs
			} // 3 tabs
		: () => { // 2 tabs
				return false // 4 tabs
			} // 3 tabs

```
ljharb: Looks right to me!
sheerun: @ljharb Because there are no changes needed in code to to format according to these examples, I've just added two more tests that verify 4-spaces and tabs indentation. I hope this makes this PR complete.
kaicataldo: I support this change, but can you speak to why you think it’s better to add `offsetTernaryExpressions` as opposed to adding a `ConditionalExpression` option?
sheerun: I don't really care what this is called. Please suggest something you're willing to merge if `offsetTernaryExpressions` doesn't suit you
sheerun: And I don't mean it in mean way, it's really irrelevant for me. I'd just ask to merge this or I can change the name to something better suiting.
sheerun: Can you merge this, please?
kaicataldo: @sheerun I support this proposal, but the team still needs to reach consensus before we can move forward. Thanks for your patience!
kaicataldo: I will champion this.
kaicataldo: @platinumazure @ilyavolodin Any thoughts on the naming of this option, as mentioned [here](https://github.com/eslint/eslint/pull/12556#issuecomment-554220017)?
platinumazure: @kaicataldo I slightly prefer the current name if the implementation is otherwise unchanged.

Some thoughts:

1. All of our other node type options in this rule use numeric values (representing offset units), rather than Boolean.
1. Also, the node type options tend to set offsets for all tokens inside the node, whereas I *think* this option is only affecting nodes/tokens within the consequent and alternate of the ternary (and not the `?` or `:` operator tokens). I suppose this might be okay for most users, but I find it unintuitive myself.
kaicataldo: That makes sense to me. Let’s stick with this API then.
sheerun: @platinumazure I've applied requested changes

I've added just one invalid example but it should cover all code paths, is it ok?
sheerun: @kaicataldo done
kaicataldo: Could we add just one valid test with the new option set to `false`? Totally fine if it’s the same test as the valid test using the default value.
sheerun: @kaicataldo done
kaicataldo: This has now been accepted.

Patch:
diff --git a/.azure-pipelines/job.yml b/.azure-pipelines/job.yml
deleted file mode 100644
index 2f8a55373..000000000
--- a/.azure-pipelines/job.yml
+++ /dev/null
@@ -1,37 +0,0 @@
-parameters:
-  name: ""
-  displayName: ""
-  vmImage: ""
-  nodeVersion: ""
-
-jobs:
-  - job: ${{parameters.name}}
-    displayName: ${{parameters.displayName}}
-    pool:
-      vmImage: ${{parameters.vmImage}}
-    steps:
-      - task: NodeTool@0
-        displayName: Install Node.js
-        inputs:
-          versionSpec: ${{parameters.nodeVersion}}
-
-      - script: npm install
-        displayName: Install Packages
-
-      - script: npm test
-        displayName: Test
-
-      - task: PublishTestResults@2
-        displayName: Process Test Results
-        condition: succeededOrFailed()
-        inputs:
-          testRunner: JUnit
-          testResultsFiles: $(System.DefaultWorkingDirectory)/test-results.xml
-
-      - task: PublishCodeCoverageResults@1
-        displayName: Process Coverage Results
-        condition: succeededOrFailed()
-        inputs: 
-          codeCoverageTool: Cobertura
-          summaryFileLocation: $(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml
-          reportDirectory: $(System.DefaultWorkingDirectory)/coverage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d02601b7a..645258a56 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,33 @@
+v6.8.0 - December 20, 2019
+
+* [`c5c7086`](https://github.com/eslint/eslint/commit/c5c708666b450fb69522a55aa375626f9297dc6f) Fix: ignore aligning single line in key-spacing (fixes #11414) (#12652) (YeonJuan)
+* [`9986d9e`](https://github.com/eslint/eslint/commit/9986d9e0baed0d3586bbee472fe2fae2ed625f5d) Chore: add object option test cases in yield-star-spacing (#12679) (YeonJuan)
+* [`1713d07`](https://github.com/eslint/eslint/commit/1713d0758b083f3840d724505f997a7cb20ff384) New: Add no-error-on-unmatched-pattern flag (fixes #10587) (#12377) (ncraley)
+* [`5c25a26`](https://github.com/eslint/eslint/commit/5c25a26608fbd9a1d0127c9a3653609aa4b63e86) Update: autofix bug in lines-between-class-members (fixes #12391) (#12632) (YeonJuan)
+* [`4b3cc5c`](https://github.com/eslint/eslint/commit/4b3cc5cd2459f04eae149faea0651785d7f9db0b) Chore: enable prefer-regex-literals in eslint codebase (#12268) (薛定谔的猫)
+* [`05faebb`](https://github.com/eslint/eslint/commit/05faebb943456ad2b20117f3c8b3eccbe2e2fb03) Update: improve suggestion testing experience (#12602) (Brad Zacher)
+* [`05f7dd5`](https://github.com/eslint/eslint/commit/05f7dd53ed91a6e3be9eb40825fb6d2207f82209) Update: Add suggestions for no-unsafe-negation (fixes #12591) (#12609) (Milos Djermanovic)
+* [`d3e43f1`](https://github.com/eslint/eslint/commit/d3e43f1c10c5e19f40e7b3d3944b87f1b0c9c075) Docs: Update no-multi-assign explanation (#12615) (Yuping Zuo)
+* [`272e4db`](https://github.com/eslint/eslint/commit/272e4db6074283bc01cc6ec72c9e396bb3c110e6) Fix: no-multiple-empty-lines: Adjust reported `loc` (#12594) (Tobias Bieniek)
+* [`a258039`](https://github.com/eslint/eslint/commit/a258039e556075d7d1f955a79d094ea103ec165a) Fix: no-restricted-imports schema allows multiple paths/patterns objects (#12639) (Milos Djermanovic)
+* [`51f9620`](https://github.com/eslint/eslint/commit/51f9620cc55cc091fe38dbe68e4633de06297b8c) Fix: improve report location for array-bracket-spacing (#12653) (Milos Djermanovic)
+* [`45364af`](https://github.com/eslint/eslint/commit/45364afc9c7f0251348cd1a7a13656c3816435d7) Fix: prefer-numeric-literals doesn't check types of literal arguments (#12655) (Milos Djermanovic)
+* [`e3c570e`](https://github.com/eslint/eslint/commit/e3c570eaf3d1d44fb57bf42f1870887856e4c5a0) Docs: Add example for expression option (#12694) (Arnaud Barré)
+* [`6b774ef`](https://github.com/eslint/eslint/commit/6b774ef0d849ccf5c1127b25e1fe7c3e438d586b) Docs: Add spacing in comments for no-console rule (#12696) (Nikki Nikkhoui)
+* [`7171fca`](https://github.com/eslint/eslint/commit/7171fca6ef4e0e8f267658fc7d8f603f00eddd84) Chore: refactor regex in config comment parser (#12662) (Milos Djermanovic)
+* [`1600648`](https://github.com/eslint/eslint/commit/1600648d2880ffb1e9e414b31ff0f66ead7167f9) Update: Allow $schema in config (#12612) (Yordis Prieto)
+* [`acc0e47`](https://github.com/eslint/eslint/commit/acc0e47572a9390292b4e313b4a4bf360d236358) Update: support .eslintrc.cjs (refs eslint/rfcs#43) (#12321) (Evan Plaice)
+* [`49c1658`](https://github.com/eslint/eslint/commit/49c1658544ace24b9aaaa301af0fc07a2ef3bf30) Chore: remove bundling of ESLint during release (#12676) (Kai Cataldo)
+* [`257f3d6`](https://github.com/eslint/eslint/commit/257f3d67905a52bf8602a5a5707c893cc90d7ca7) Chore: complete to move to GitHub Actions (#12625) (Toru Nagashima)
+* [`ab912f0`](https://github.com/eslint/eslint/commit/ab912f0ef709a916ab9a27ea09d9d7adf046fb2d) Docs: 1tbs with allowSingleLine edge cases (refs #12284) (#12314) (Ari Kardasis)
+* [`dd1c30e`](https://github.com/eslint/eslint/commit/dd1c30e35f05ed332e2abbd3d4d53635efde74b8) Sponsors: Sync README with website (ESLint Jenkins)
+* [`a230f84`](https://github.com/eslint/eslint/commit/a230f8404e4f2423dd79378b065d24c12776775b) Update: include node version in cache (#12582) (Eric Wang)
+* [`8b65f17`](https://github.com/eslint/eslint/commit/8b65f175dfb4fac11ed7184537be400ed14996fb) Chore: remove references to parser demo (#12644) (Kai Cataldo)
+* [`e9cef99`](https://github.com/eslint/eslint/commit/e9cef99e6ebec1faefdb576ca597e81ae4f04afd) Docs: wrap {{}} in raw liquid tags to prevent interpolation (#12643) (Kai Cataldo)
+* [`e707453`](https://github.com/eslint/eslint/commit/e70745325ff9e085acc6843dd8bfae5550645d4f) Docs: Fix configuration example in no-restricted-imports (fixes #11717) (#12638) (Milos Djermanovic)
+* [`19194ce`](https://github.com/eslint/eslint/commit/19194cec724e016df02376bbeae31171be6f0bdf) Chore: Add tests to cover default object options in comma-dangle (#12627) (YeonJuan)
+* [`6e36d12`](https://github.com/eslint/eslint/commit/6e36d12d95e76022172fd0ec8a5e85c22fde6a8a) Update: do not recommend require-atomic-updates (refs #11899) (#12599) (Kai Cataldo)
+
 v6.7.2 - November 30, 2019
 
 * [`bc435a9`](https://github.com/eslint/eslint/commit/bc435a93afd6ba4def1b53993ef7cf8220f3f070) Fix: isSpaceBetweenTokens() recognizes spaces in JSXText (fixes #12614) (#12616) (Toru Nagashima)
diff --git a/Makefile.js b/Makefile.js
index 1b241c1ae..2dc8547f3 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -560,7 +560,7 @@ target.mocha = () => {
 target.karma = () => {
     echo("Running unit tests on browsers");
 
-    target.webpack();
+    target.webpack("production");
 
     const browserFileLintOutput = new CLIEngine({
         useEslintrc: false,
@@ -775,17 +775,7 @@ target.gensite = function(prereleaseVersion) {
     echo("> Removing the temporary directory (Step 12)");
     rm("-rf", TEMP_DIR);
 
-    // 13. Update demos, but only for non-prereleases
-    if (!prereleaseVersion) {
-        echo("> Updating the demos (Step 13)");
-        target.webpack("production");
-        cp("-f", "build/eslint.js", `${SITE_DIR}src/js/eslint.js`);
-        cp("-f", "build/espree.js", `${SITE_DIR}src/js/espree.js`);
-    } else {
-        echo("> Skipped updating the demos (Step 13)");
-    }
-
-    // 14. Create Example Formatter Output Page
+    // 13. Create Example Formatter Output Page
     echo("> Creating the formatter examples (Step 14)");
     generateFormatterExamples(getFormatterResults(), prereleaseVersion);
 
diff --git a/README.md b/README.md
index 0e574e5b2..0cde09fc6 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
 [![NPM version][npm-image]][npm-url]
-[![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master)
 [![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
 [![Downloads][downloads-image]][downloads-url]
 [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
@@ -265,7 +264,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <h3>Gold Sponsors</h3>
 <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/badoo/2826a3b/logo.png" alt="Badoo" 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://opensource.facebook.com"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" 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/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://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://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
+<p><a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" height="32"></a> <a href="https://www.codacy.com/?utm_source=eslint&utm_medium=cpm&utm_campaign=eslint-sponsorship"><img src="https://images.opencollective.com/codacy/ed22716/logo.png" alt="Codacy" 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/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://edubirdie.com/"><img src="https://images.opencollective.com/edubirdie2/b1d51ab/logo.png" alt="EduBirdie" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://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://jsheroes.io/"><img src="https://images.opencollective.com/jsheroes1/9fedf0b/logo.png" alt="JSHeroes " height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
deleted file mode 100644
index 13a2f38c4..000000000
--- a/azure-pipelines.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-trigger:
-  - master
-
-jobs:
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node12
-      displayName: Test on Node.js 12 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 12.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node10
-      displayName: Test on Node.js 10 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 10.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_linux_node8
-      displayName: Test on Node.js 8 (Linux)
-      vmImage: Ubuntu-16.04
-      nodeVersion: 8.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_windows_node12
-      displayName: Test on Node.js 12 (Windows)
-      vmImage: Windows-2019
-      nodeVersion: 12.x
-
-  - template: .azure-pipelines/job.yml
-    parameters:
-      name: test_on_macos_node12
-      displayName: Test on Node.js 12 (macOS)
-      vmImage: macOS-10.14
-      nodeVersion: 12.x
diff --git a/conf/config-schema.js b/conf/config-schema.js
index 83addff87..712fc4235 100644
--- a/conf/config-schema.js
+++ b/conf/config-schema.js
@@ -6,6 +6,7 @@
 "use strict";
 
 const baseConfigProperties = {
+    $schema: { type: "string" },
     env: { type: "object" },
     extends: { $ref: "#/definitions/stringOrStrings" },
     globals: { type: "object" },
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 7cc6e0165..e915ec449 100644
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -62,7 +62,6 @@ module.exports = {
         "no-useless-catch": "error",
         "no-useless-escape": "error",
         "no-with": "error",
-        "require-atomic-updates": "error",
         "require-yield": "error",
         "use-isnan": "error",
         "valid-typeof": "error"
diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md
index bceb9ee8f..deac450b0 100644
--- a/docs/developer-guide/working-with-rules.md
+++ b/docs/developer-guide/working-with-rules.md
@@ -352,6 +352,7 @@ In some cases fixes aren't appropriate to be automatically applied, for example,
 In order to provide suggestions, use the `suggest` key in the report argument with an array of suggestion objects. The suggestion objects represent individual suggestions that could be applied and require either a `desc` key string that describes what applying the suggestion would do or a `messageId` key (see [below](#suggestion-messageids)), and a `fix` key that is a function defining the suggestion result. This `fix` function follows the same API as regular fixes (described above in [applying fixes](#applying-fixes)).
 
 ```js
+{% raw %}
 context.report({
     node: node,
     message: "Unnecessary escape character: \\{{character}}.",
@@ -371,6 +372,7 @@ context.report({
         }
     ]
 });
+{% endraw %}
 ```
 
 Note: Suggestions will be applied as a stand-alone change, without triggering multipass fixes. Each suggestion should focus on a singular change in the code and should not try to conform to user defined styles. For example, if a suggestion is adding a new statement into the codebase, it should not try to match correct indentation, or confirm to user preferences on presence/absence of semicolumns. All of those things can be corrected by multipass autofix when the user triggers it.
@@ -385,6 +387,7 @@ Best practices for suggestions:
 Instead of using a `desc` key for suggestions a `messageId` can be used instead. This works the same way as `messageId`s for the overall error (see [messageIds](#messageIds)). Here is an example of how to use it in a rule:
 
 ```js
+{% raw %}
 module.exports = {
     meta: {
         messages: {
@@ -416,6 +419,7 @@ module.exports = {
         });
     }
 };
+{% endraw %}
 ```
 
 #### Placeholders in suggestion messages
@@ -425,6 +429,7 @@ You can also use placeholders in the suggestion message. This works the same way
 Please note that you have to provide `data` on the suggestion's object. Suggestion messages cannot use properties from the overall error's `data`.
 
 ```js
+{% raw %}
 module.exports = {
     meta: {
         messages: {
@@ -450,6 +455,7 @@ module.exports = {
         });
     }
 };
+{% endraw %}
 ```
 
 ### context.options
diff --git a/docs/rules/brace-style.md b/docs/rules/brace-style.md
index 37098b1cd..dce2d9649 100644
--- a/docs/rules/brace-style.md
+++ b/docs/rules/brace-style.md
@@ -129,6 +129,27 @@ if (foo) { bar(); }
 if (foo) { bar(); } else { baz(); }
 
 try { somethingRisky(); } catch(e) { handleError(); }
+
+if (foo) { baz(); } else {
+  boom();
+}
+
+if (foo) { baz(); } else if (bar) {
+  boom();
+}
+
+if (foo) { baz(); } else
+if (bar) {
+  boom();
+}
+
+if (foo) { baz); } else if (bar) {
+  boom();
+}
+
+try { somethingRisky(); } catch(e) {
+  handleError();
+}
 ```
 
 ### stroustrup
diff --git a/docs/rules/comma-style.md b/docs/rules/comma-style.md
index 2a55dbf58..24b551574 100644
--- a/docs/rules/comma-style.md
+++ b/docs/rules/comma-style.md
@@ -39,7 +39,7 @@ This rule also accepts an additional `exceptions` object:
     * `"VariableDeclaration": true` ignores comma style in variable declarations
     * `"NewExpression": true` ignores comma style in the parameters of constructor expressions
 
-A way to determine the node types as defined by [ESTree](https://github.com/estree/estree) is to use the [online demo](https://eslint.org/parser).
+A way to determine the node types as defined by [ESTree](https://github.com/estree/estree) is to use [AST Explorer](https://astexplorer.net/) with the espree parser.
 
 ### last
 
diff --git a/docs/rules/func-style.md b/docs/rules/func-style.md
index 14f01b0c4..e17fecf8f 100644
--- a/docs/rules/func-style.md
+++ b/docs/rules/func-style.md
@@ -77,6 +77,8 @@ Examples of **correct** code for this rule with the default `"expression"` optio
 var foo = function() {
     // ...
 };
+
+var foo = () => {};
 ```
 
 ### declaration
diff --git a/docs/rules/indent.md b/docs/rules/indent.md
index 0e58352fc..8d7f9d059 100644
--- a/docs/rules/indent.md
+++ b/docs/rules/indent.md
@@ -84,6 +84,7 @@ This rule has an object option:
 * `"ObjectExpression"` (default: 1) enforces indentation level for properties in objects. It can be set to the string `"first"`, indicating that all properties in the object should be aligned with the first property. This can also be set to `"off"` to disable checking for object properties.
 * `"ImportDeclaration"` (default: 1) enforces indentation level for import statements. It can be set to the string `"first"`, indicating that all imported members from a module should be aligned with the first member in the list. This can also be set to `"off"` to disable checking for imported module members.
 * `"flatTernaryExpressions": true` (`false` by default) requires no indentation for ternary expressions which are nested in other ternary expressions.
+* `"offsetTernaryExpressions": true` (`false` by default) requires indentation for values of ternary expressions.
 * `"ignoredNodes"` accepts an array of [selectors](/docs/developer-guide/selectors.md). If an AST node is matched by any of the selectors, the indentation of tokens which are direct children of that node will be ignored. This can be used as an escape hatch to relax the rule if you disagree with the indentation that it enforces for a particular syntactic pattern.
 * `"ignoreComments"` (default: false) can be used when comments do not need to be aligned with nodes on the previous or next line.
 
@@ -643,6 +644,76 @@ var a =
     boop;
 ```
 
+### offsetTernaryExpressions
+
+Examples of **incorrect** code for this rule with the default `2, { "offsetTernaryExpressions": false }` option:
+
+```js
+/*eslint indent: ["error", 2, { "offsetTernaryExpressions": false }]*/
+
+condition
+  ? () => {
+      return true
+    }
+  : () => {
+      false
+    }
+```
+
+Examples of **correct** code for this rule with the default `2, { "offsetTernaryExpressions": false }` option:
+
+```js
+/*eslint indent: ["error", 2, { "offsetTernaryExpressions": false }]*/
+
+condition
+  ? () => {
+    return true
+  }
+  : condition2
+    ? () => {
+      return true
+    }
+    : () => {
+      return false
+    }
+```
+
+Examples of **incorrect** code for this rule with the `2, { "offsetTernaryExpressions": true }` option:
+
+```js
+/*eslint indent: ["error", 2, { "offsetTernaryExpressions": true }]*/
+
+condition
+  ? () => {
+    return true
+  }
+  : condition2
+    ? () => {
+      return true
+    }
+    : () => {
+      return false
+    }
+```
+
+Examples of **correct** code for this rule with the `2, { "offsetTernaryExpressions": true }` option:
+
+```js
+/*eslint indent: ["error", 2, { "offsetTernaryExpressions": true }]*/
+
+condition
+  ? () => {
+      return true
+    }
+  : condition2
+    ? () => {
+        return true
+      }
+    : () => {
+        return false
+      }
+```
+
 ### ignoredNodes
 
 The following configuration ignores the indentation of `ConditionalExpression` ("ternary expression") nodes:
diff --git a/docs/rules/no-console.md b/docs/rules/no-console.md
index bc163b937..f2fb79ec4 100644
--- a/docs/rules/no-console.md
+++ b/docs/rules/no-console.md
@@ -14,7 +14,7 @@ This rule disallows calls to methods of the `console` object.
 Examples of **incorrect** code for this rule:
 
 ```js
-/*eslint no-console: "error"*/
+/* eslint no-console: "error" */
 
 console.log("Log a debug level message.");
 console.warn("Log a warn level message.");
@@ -24,7 +24,7 @@ console.error("Log an error level message.");
 Examples of **correct** code for this rule:
 
 ```js
-/*eslint no-console: "error"*/
+/* eslint no-console: "error" */
 
 // custom console
 Console.log("Hello world!");
@@ -39,7 +39,7 @@ This rule has an object option for exceptions:
 Examples of additional **correct** code for this rule with a sample `{ "allow": ["warn", "error"] }` option:
 
 ```js
-/*eslint no-console: ["error", { allow: ["warn", "error"] }] */
+/* eslint no-console: ["error", { allow: ["warn", "error"] }] */
 
 console.warn("Log a warn level message.");
 console.error("Log an error level message.");
@@ -52,7 +52,7 @@ If you're using Node.js, however, `console` is used to output information to the
 Another case where you might not use this rule is if you want to enforce console calls and not console overwrites. For example:
 
 ```js
-/*eslint no-console: ["error", { allow: ["warn"] }] */
+/* eslint no-console: ["error", { allow: ["warn"] }] */
 console.error = function (message) {
   throw new Error(message);
 };
diff --git a/docs/rules/no-multi-assign.md b/docs/rules/no-multi-assign.md
index 2da09ba07..41bba9ad6 100644
--- a/docs/rules/no-multi-assign.md
+++ b/docs/rules/no-multi-assign.md
@@ -3,7 +3,11 @@
 Chaining the assignment of variables can lead to unexpected results and be difficult to read.
 
 ```js
-a = b = c = d;
+(function() {
+    const foo = bar = 0; // Did you mean `foo = bar == 0`?
+    bar = 1;             // This will not fail since `bar` is not constant.
+})();
+console.log(bar);        // This will output 1 since `bar` is not scoped.
 ```
 
 ## Rule Details
@@ -17,9 +21,9 @@ Examples of **incorrect** code for this rule:
 
 var a = b = c = 5;
 
-var foo = bar = "baz";
+const foo = bar = "baz";
 
-var a =
+let a =
     b =
     c;
 ```
@@ -32,11 +36,11 @@ var a = 5;
 var b = 5;
 var c = 5;
 
-var foo = "baz";
-var bar = "baz";
+const foo = "baz";
+const bar = "baz";
 
-var a = c;
-var b = c;
+let a = c;
+let b = c;
 ```
 
 ## Related Rules
diff --git a/docs/rules/no-multi-spaces.md b/docs/rules/no-multi-spaces.md
index 07cd0e901..c4b12e938 100644
--- a/docs/rules/no-multi-spaces.md
+++ b/docs/rules/no-multi-spaces.md
@@ -102,7 +102,7 @@ var x = 5;      /* multiline
 
 To avoid contradictions with other rules that require multiple spaces, this rule has an `exceptions` option to ignore certain nodes.
 
-This option is an object that expects property names to be AST node types as defined by [ESTree](https://github.com/estree/estree). The easiest way to determine the node types for `exceptions` is to use the [online demo](https://eslint.org/parser).
+This option is an object that expects property names to be AST node types as defined by [ESTree](https://github.com/estree/estree). The easiest way to determine the node types for `exceptions` is to use [AST Explorer](https://astexplorer.net/) with the espree parser.
 
 Only the `Property` node type is ignored by default, because for the [key-spacing](key-spacing.md) rule some alignment options require multiple spaces in properties of object literals.
 
diff --git a/docs/rules/no-param-reassign.md b/docs/rules/no-param-reassign.md
index 2ee312c2b..47a7af3cb 100644
--- a/docs/rules/no-param-reassign.md
+++ b/docs/rules/no-param-reassign.md
@@ -129,17 +129,25 @@ Examples of **correct** code for the `{ "props": true }` option with `"ignorePro
 ```js
 /*eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsForRegex": ["^bar"] }]*/
 
-function foo(bar) {
+function foo(barVar) {
     barVar.prop = "value";
 }
 
-function foo(bar) {
+function foo(barrito) {
     delete barrito.aaa;
 }
 
-function foo(bar) {
+function foo(bar_) {
     bar_.aaa++;
 }
+
+function foo(barBaz) {
+    for (barBaz.aaa in baz) {}
+}
+
+function foo(barBaz) {
+    for (barBaz.aaa of baz) {}
+}
 ```
 
 
diff --git a/docs/rules/no-restricted-imports.md b/docs/rules/no-restricted-imports.md
index 62747ebce..e86544d2e 100644
--- a/docs/rules/no-restricted-imports.md
+++ b/docs/rules/no-restricted-imports.md
@@ -38,20 +38,26 @@ When using the object form, you can also specify an array of gitignore-style pat
 You may also specify a custom message for any paths you want to restrict as follows:
 
 ```json
-"no-restricted-imports": ["error", [{
-  "name": "import-foo",
-  "message": "Please use import-bar instead."
-}]]
+"no-restricted-imports": ["error", {
+    "name": "import-foo",
+    "message": "Please use import-bar instead."
+}, {
+    "name": "import-baz",
+    "message": "Please use import-quux instead."
+}]
 ```
 
 or like this:
 
 ```json
 "no-restricted-imports": ["error", {
-  "paths": [{
-    "name": "import-foo",
-    "message": "Please use import-bar instead."
-  }]
+    "paths": [{
+        "name": "import-foo",
+        "message": "Please use import-bar instead."
+    }, {
+        "name": "import-baz",
+        "message": "Please use import-quux instead."
+    }]
 }]
 ```
 
diff --git a/docs/rules/no-restricted-syntax.md b/docs/rules/no-restricted-syntax.md
index 37dbe8f01..066516721 100644
--- a/docs/rules/no-restricted-syntax.md
+++ b/docs/rules/no-restricted-syntax.md
@@ -2,7 +2,7 @@
 
 JavaScript has a lot of language features, and not everyone likes all of them. As a result, some projects choose to disallow the use of certain language features altogether. For instance, you might decide to disallow the use of `try-catch` or `class`, or you might decide to disallow the use of the `in` operator.
 
-Rather than creating separate rules for every language feature you want to turn off, this rule allows you to configure the syntax elements you want to restrict use of. These elements are represented by their [ESTree](https://github.com/estree/estree) node types. For example, a function declaration is represented by `FunctionDeclaration` and the `with` statement is represented by `WithStatement`. You may find the full list of AST node names you can use [on GitHub](https://github.com/eslint/espree/blob/master/lib/ast-node-types.js) and use the [online parser](https://eslint.org/parser/) to see what type of nodes your code consists of.
+Rather than creating separate rules for every language feature you want to turn off, this rule allows you to configure the syntax elements you want to restrict use of. These elements are represented by their [ESTree](https://github.com/estree/estree) node types. For example, a function declaration is represented by `FunctionDeclaration` and the `with` statement is represented by `WithStatement`. You may find the full list of AST node names you can use [on GitHub](https://github.com/eslint/espree/blob/master/lib/ast-node-types.js) and use [AST Explorer](https://astexplorer.net/) with the espree parser to see what type of nodes your code consists of.
 
 You can also specify [AST selectors](../developer-guide/selectors) to restrict, allowing much more precise control over syntax patterns.
 
diff --git a/docs/user-guide/command-line-interface.md b/docs/user-guide/command-line-interface.md
index c8871b07d..89f42744e 100644
--- a/docs/user-guide/command-line-interface.md
+++ b/docs/user-guide/command-line-interface.md
@@ -79,6 +79,7 @@ Caching:
 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
   --debug                        Output debugging information
   -h, --help                     Show help
   -v, --version                  Output the version number
@@ -451,6 +452,10 @@ The resulting configuration file will be created in the current directory.
 
 This option outputs information about the execution environment, including the version of Node, npm, and local and global installations of ESLint. The ESLint team may ask for this information to help solve bugs.
 
+#### `--no-error-on-unmatched-pattern`
+
+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.
+
 #### `--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.md b/docs/user-guide/configuring.md
index 5022fc44d..2a47a3e9e 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -664,6 +664,7 @@ In each case, the settings in the configuration file override default settings.
 ESLint supports configuration files in several formats:
 
 * **JavaScript** - use `.eslintrc.js` and export an object containing your configuration.
+* **JavaScript (ESM)** - use `.eslintrc.cjs` when running ESLint in JavaScript packages that specify `"type":"module"` in their `package.json`. Note that ESLint does not support ESM configuration at this time.
 * **YAML** - use `.eslintrc.yaml` or `.eslintrc.yml` to define the configuration structure.
 * **JSON** - use `.eslintrc.json` to define the configuration structure. ESLint's JSON files also allow JavaScript-style comments.
 * **Deprecated** - use `.eslintrc`, which can be either JSON or YAML.
@@ -672,13 +673,13 @@ ESLint supports configuration files in several formats:
 If there are multiple configuration files in the same directory, ESLint will only use one. The priority order is:
 
 1. `.eslintrc.js`
+1. `.eslintrc.cjs`
 1. `.eslintrc.yaml`
 1. `.eslintrc.yml`
 1. `.eslintrc.json`
 1. `.eslintrc`
 1. `package.json`
 
-
 ## Configuration Cascading and Hierarchy
 
 When using `.eslintrc.*` and `package.json` files for configuration, you can take advantage of configuration cascading. For instance, suppose you have the following structure:
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index 0b1c76bac..22336a91d 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -576,6 +576,7 @@ class CLIEngine {
             cwd: options.cwd,
             extensions: options.extensions,
             globInputPaths: options.globInputPaths,
+            errorOnUnmatchedPattern: options.errorOnUnmatchedPattern,
             ignore: options.ignore
         });
         const lintResultCache =
diff --git a/lib/cli-engine/config-array-factory.js b/lib/cli-engine/config-array-factory.js
index c444031bc..76c4ccd70 100644
--- a/lib/cli-engine/config-array-factory.js
+++ b/lib/cli-engine/config-array-factory.js
@@ -62,6 +62,7 @@ const eslintRecommendedPath = path.resolve(__dirname, "../../conf/eslint-recomme
 const eslintAllPath = path.resolve(__dirname, "../../conf/eslint-all.js");
 const configFilenames = [
     ".eslintrc.js",
+    ".eslintrc.cjs",
     ".eslintrc.yaml",
     ".eslintrc.yml",
     ".eslintrc.json",
@@ -279,6 +280,7 @@ function configMissingError(configName, importerName) {
 function loadConfigFile(filePath) {
     switch (path.extname(filePath)) {
         case ".js":
+        case ".cjs":
             return loadJSConfigFile(filePath);
 
         case ".json":
diff --git a/lib/cli-engine/file-enumerator.js b/lib/cli-engine/file-enumerator.js
index b5a082b71..c67e01aef 100644
--- a/lib/cli-engine/file-enumerator.js
+++ b/lib/cli-engine/file-enumerator.js
@@ -190,6 +190,7 @@ class FileEnumerator {
         configArrayFactory = new CascadingConfigArrayFactory({ cwd }),
         extensions = [".js"],
         globInputPaths = true,
+        errorOnUnmatchedPattern = true,
         ignore = true
     } = {}) {
         internalSlotsMap.set(this, {
@@ -208,6 +209,7 @@ class FileEnumerator {
                 "u"
             ),
             globInputPaths,
+            errorOnUnmatchedPattern,
             ignoreFlag: ignore
         });
     }
@@ -226,7 +228,7 @@ class FileEnumerator {
      * @returns {IterableIterator<FileAndConfig>} The found files.
      */
     *iterateFiles(patternOrPatterns) {
-        const { globInputPaths } = internalSlotsMap.get(this);
+        const { globInputPaths, errorOnUnmatchedPattern } = internalSlotsMap.get(this);
         const patterns = Array.isArray(patternOrPatterns)
             ? patternOrPatterns
             : [patternOrPatterns];
@@ -265,14 +267,16 @@ class FileEnumerator {
             }
 
             // Raise an error if any files were not found.
-            if (!foundRegardlessOfIgnored) {
-                throw new NoFilesFoundError(
-                    pattern,
-                    !globInputPaths && isGlob(pattern)
-                );
-            }
-            if (!found) {
-                throw new AllFilesIgnoredError(pattern);
+            if (errorOnUnmatchedPattern) {
+                if (!foundRegardlessOfIgnored) {
+                    throw new NoFilesFoundError(
+                        pattern,
+                        !globInputPaths && isGlob(pattern)
+                    );
+                }
+                if (!found) {
+                    throw new AllFilesIgnoredError(pattern);
+                }
             }
         }
 
diff --git a/lib/cli-engine/lint-result-cache.js b/lib/cli-engine/lint-result-cache.js
index 14e19d9e5..23a142097 100644
--- a/lib/cli-engine/lint-result-cache.js
+++ b/lib/cli-engine/lint-result-cache.js
@@ -20,6 +20,7 @@ const hash = require("./hash");
 //-----------------------------------------------------------------------------
 
 const configHashCache = new WeakMap();
+const nodeVersion = process && process.version;
 
 /**
  * Calculates the hash of the config
@@ -28,7 +29,7 @@ const configHashCache = new WeakMap();
  */
 function hashOfConfigFor(config) {
     if (!configHashCache.has(config)) {
-        configHashCache.set(config, hash(`${pkg.version}_${stringify(config)}`));
+        configHashCache.set(config, hash(`${pkg.version}_${nodeVersion}_${stringify(config)}`));
     }
 
     return configHashCache.get(config);
diff --git a/lib/cli.js b/lib/cli.js
index 18a917cf0..944b4b793 100644
--- a/lib/cli.js
+++ b/lib/cli.js
@@ -68,7 +68,8 @@ function translateOptions(cliOptions) {
         fixTypes: cliOptions.fixType,
         allowInlineConfig: cliOptions.inlineConfig,
         reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives,
-        resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo
+        resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo,
+        errorOnUnmatchedPattern: cliOptions.errorOnUnmatchedPattern
     };
 }
 
diff --git a/lib/linter/config-comment-parser.js b/lib/linter/config-comment-parser.js
index d0e24c594..35862315d 100644
--- a/lib/linter/config-comment-parser.js
+++ b/lib/linter/config-comment-parser.js
@@ -90,7 +90,7 @@ module.exports = class ConfigCommentParser {
          * But we are supporting that. So this is a fallback for that.
          */
         items = {};
-        const normalizedString = string.replace(/([a-zA-Z0-9\-/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
+        const normalizedString = string.replace(/([-a-zA-Z0-9/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,");
 
         try {
             items = JSON.parse(`{${normalizedString}}`);
diff --git a/lib/options.js b/lib/options.js
index 83bf9afc2..98dc04b6e 100644
--- a/lib/options.js
+++ b/lib/options.js
@@ -230,6 +230,12 @@ module.exports = optionator({
             default: "false",
             description: "Output execution environment information"
         },
+        {
+            option: "error-on-unmatched-pattern",
+            type: "Boolean",
+            default: "true",
+            description: "Prevent errors when pattern is unmatched"
+        },
         {
             option: "debug",
             type: "Boolean",
diff --git a/lib/rules/array-bracket-spacing.js b/lib/rules/array-bracket-spacing.js
index 2510159ee..c2b77a641 100644
--- a/lib/rules/array-bracket-spacing.js
+++ b/lib/rules/array-bracket-spacing.js
@@ -84,16 +84,16 @@ module.exports = {
          * @returns {void}
          */
         function reportNoBeginningSpace(node, token) {
+            const nextToken = sourceCode.getTokenAfter(token);
+
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: { start: token.loc.end, end: nextToken.loc.start },
                 messageId: "unexpectedSpaceAfter",
                 data: {
                     tokenValue: token.value
                 },
                 fix(fixer) {
-                    const nextToken = sourceCode.getTokenAfter(token);
-
                     return fixer.removeRange([token.range[1], nextToken.range[0]]);
                 }
             });
@@ -106,16 +106,16 @@ module.exports = {
          * @returns {void}
          */
         function reportNoEndingSpace(node, token) {
+            const previousToken = sourceCode.getTokenBefore(token);
+
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: { start: previousToken.loc.end, end: token.loc.start },
                 messageId: "unexpectedSpaceBefore",
                 data: {
                     tokenValue: token.value
                 },
                 fix(fixer) {
-                    const previousToken = sourceCode.getTokenBefore(token);
-
                     return fixer.removeRange([previousToken.range[1], token.range[0]]);
                 }
             });
@@ -130,7 +130,7 @@ module.exports = {
         function reportRequiredBeginningSpace(node, token) {
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: token.loc,
                 messageId: "missingSpaceAfter",
                 data: {
                     tokenValue: token.value
@@ -150,7 +150,7 @@ module.exports = {
         function reportRequiredEndingSpace(node, token) {
             context.report({
                 node,
-                loc: token.loc.start,
+                loc: token.loc,
                 messageId: "missingSpaceBefore",
                 data: {
                     tokenValue: token.value
diff --git a/lib/rules/indent.js b/lib/rules/indent.js
index 694cf7d9e..9fa62c84a 100644
--- a/lib/rules/indent.js
+++ b/lib/rules/indent.js
@@ -590,6 +590,10 @@ module.exports = {
                         type: "boolean",
                         default: false
                     },
+                    offsetTernaryExpressions: {
+                        type: "boolean",
+                        default: false
+                    },
                     ignoredNodes: {
                         type: "array",
                         items: {
@@ -1142,7 +1146,8 @@ module.exports = {
                     offsets.setDesiredOffset(questionMarkToken, firstToken, 1);
                     offsets.setDesiredOffset(colonToken, firstToken, 1);
 
-                    offsets.setDesiredOffset(firstConsequentToken, firstToken, 1);
+                    offsets.setDesiredOffset(firstConsequentToken, firstToken,
+                        options.offsetTernaryExpressions ? 2 : 1);
 
                     /*
                      * The alternate and the consequent should usually have the same indentation.
@@ -1167,7 +1172,9 @@ module.exports = {
                          * If `baz` were aligned with `bar` rather than being offset by 1 from `foo`, `baz` would end up
                          * having no expected indentation.
                          */
-                        offsets.setDesiredOffset(firstAlternateToken, firstToken, 1);
+                        offsets.setDesiredOffset(firstAlternateToken, firstToken,
+                            firstAlternateToken.type === "Punctuator" &&
+                            options.offsetTernaryExpressions ? 2 : 1);
                     }
                 }
             },
diff --git a/lib/rules/key-spacing.js b/lib/rules/key-spacing.js
index 994c35627..6d1b9121c 100644
--- a/lib/rules/key-spacing.js
+++ b/lib/rules/key-spacing.js
@@ -42,6 +42,18 @@ function isSingleLine(node) {
     return (node.loc.end.line === node.loc.start.line);
 }
 
+/**
+ * Checks whether the properties on a single line.
+ * @param {ASTNode[]} properties List of Property AST nodes.
+ * @returns {boolean} True if all properies is on a single line.
+ */
+function isSingleLineProperties(properties) {
+    const [firstProp] = properties,
+        lastProp = last(properties);
+
+    return firstProp.loc.start.line === lastProp.loc.end.line;
+}
+
 /**
  * Initializes a single option property from the configuration with defaults for undefined values
  * @param {Object} toOptions Object to be initialized
@@ -583,17 +595,6 @@ module.exports = {
             }
         }
 
-        /**
-         * Verifies vertical alignment, taking into account groups of properties.
-         * @param  {ASTNode} node ObjectExpression node being evaluated.
-         * @returns {void}
-         */
-        function verifyAlignment(node) {
-            createGroups(node).forEach(group => {
-                verifyGroupAlignment(group.filter(isKeyValueProperty));
-            });
-        }
-
         /**
          * Verifies spacing of property conforms to specified options.
          * @param  {ASTNode} node Property node being evaluated.
@@ -611,17 +612,35 @@ module.exports = {
 
         /**
          * Verifies spacing of each property in a list.
-         * @param  {ASTNode[]} properties List of Property AST nodes.
+         * @param {ASTNode[]} properties List of Property AST nodes.
+         * @param {Object} lineOptions Configured singleLine or multiLine options
          * @returns {void}
          */
-        function verifyListSpacing(properties) {
+        function verifyListSpacing(properties, lineOptions) {
             const length = properties.length;
 
             for (let i = 0; i < length; i++) {
-                verifySpacing(properties[i], singleLineOptions);
+                verifySpacing(properties[i], lineOptions);
             }
         }
 
+        /**
+         * Verifies vertical alignment, taking into account groups of properties.
+         * @param  {ASTNode} node ObjectExpression node being evaluated.
+         * @returns {void}
+         */
+        function verifyAlignment(node) {
+            createGroups(node).forEach(group => {
+                const properties = group.filter(isKeyValueProperty);
+
+                if (properties.length > 0 && isSingleLineProperties(properties)) {
+                    verifyListSpacing(properties, multiLineOptions);
+                } else {
+                    verifyGroupAlignment(properties);
+                }
+            });
+        }
+
         //--------------------------------------------------------------------------
         // Public API
         //--------------------------------------------------------------------------
@@ -631,7 +650,7 @@ module.exports = {
             return {
                 ObjectExpression(node) {
                     if (isSingleLine(node)) {
-                        verifyListSpacing(node.properties.filter(isKeyValueProperty));
+                        verifyListSpacing(node.properties.filter(isKeyValueProperty), singleLineOptions);
                     } else {
                         verifyAlignment(node);
                     }
diff --git a/lib/rules/lines-between-class-members.js b/lib/rules/lines-between-class-members.js
index 60332a1b3..972353036 100644
--- a/lib/rules/lines-between-class-members.js
+++ b/lib/rules/lines-between-class-members.js
@@ -54,62 +54,45 @@ module.exports = {
         const sourceCode = context.getSourceCode();
 
         /**
-         * Checks if there is padding between two tokens
-         * @param {Token} first The first token
-         * @param {Token} second The second token
-         * @returns {boolean} True if there is at least a line between the tokens
+         * Return the last token among the consecutive tokens that have no exceed max line difference in between, before the first token in the next member.
+         * @param {Token} prevLastToken The last token in the previous member node.
+         * @param {Token} nextFirstToken The first token in the next member node.
+         * @param {number} maxLine The maximum number of allowed line difference between consecutive tokens.
+         * @returns {Token} The last token among the consecutive tokens.
          */
-        function isPaddingBetweenTokens(first, second) {
-            const comments = sourceCode.getCommentsBefore(second);
-            const len = comments.length;
+        function findLastConsecutiveTokenAfter(prevLastToken, nextFirstToken, maxLine) {
+            const after = sourceCode.getTokenAfter(prevLastToken, { includeComments: true });
 
-            // If there is no comments
-            if (len === 0) {
-                const linesBetweenFstAndSnd = second.loc.start.line - first.loc.end.line - 1;
-
-                return linesBetweenFstAndSnd >= 1;
-            }
-
-
-            // If there are comments
-            let sumOfCommentLines = 0; // the numbers of lines of comments
-            let prevCommentLineNum = -1; // line number of the end of the previous comment
-
-            for (let i = 0; i < len; i++) {
-                const commentLinesOfThisComment = comments[i].loc.end.line - comments[i].loc.start.line + 1;
-
-                sumOfCommentLines += commentLinesOfThisComment;
-
-                /*
-                 * If this comment and the previous comment are in the same line,
-                 * the count of comment lines is duplicated. So decrement sumOfCommentLines.
-                 */
-                if (prevCommentLineNum === comments[i].loc.start.line) {
-                    sumOfCommentLines -= 1;
-                }
-
-                prevCommentLineNum = comments[i].loc.end.line;
+            if (after !== nextFirstToken && after.loc.start.line - prevLastToken.loc.end.line <= maxLine) {
+                return findLastConsecutiveTokenAfter(after, nextFirstToken, maxLine);
             }
+            return prevLastToken;
+        }
 
-            /*
-             * If the first block and the first comment are in the same line,
-             * the count of comment lines is duplicated. So decrement sumOfCommentLines.
-             */
-            if (first.loc.end.line === comments[0].loc.start.line) {
-                sumOfCommentLines -= 1;
-            }
+        /**
+         * Return the first token among the consecutive tokens that have no exceed max line difference in between, after the last token in the previous member.
+         * @param {Token} nextFirstToken The first token in the next member node.
+         * @param {Token} prevLastToken The last token in the previous member node.
+         * @param {number} maxLine The maximum number of allowed line difference between consecutive tokens.
+         * @returns {Token} The first token among the consecutive tokens.
+         */
+        function findFirstConsecutiveTokenBefore(nextFirstToken, prevLastToken, maxLine) {
+            const before = sourceCode.getTokenBefore(nextFirstToken, { includeComments: true });
 
-            /*
-             * If the last comment and the second block are in the same line,
-             * the count of comment lines is duplicated. So decrement sumOfCommentLines.
-             */
-            if (comments[len - 1].loc.end.line === second.loc.start.line) {
-                sumOfCommentLines -= 1;
+            if (before !== prevLastToken && nextFirstToken.loc.start.line - before.loc.end.line <= maxLine) {
+                return findFirstConsecutiveTokenBefore(before, prevLastToken, maxLine);
             }
+            return nextFirstToken;
+        }
 
-            const linesBetweenFstAndSnd = second.loc.start.line - first.loc.end.line - 1;
-
-            return linesBetweenFstAndSnd - sumOfCommentLines >= 1;
+        /**
+         * Checks if there is a token or comment between two tokens.
+         * @param {Token} before The token before.
+         * @param {Token} after The token after.
+         * @returns {boolean} True if there is a token or comment between two tokens.
+         */
+        function hasTokenOrCommentBetween(before, after) {
+            return sourceCode.getTokensBetween(before, after, { includeComments: true }).length !== 0;
         }
 
         return {
@@ -120,10 +103,13 @@ module.exports = {
                     const curFirst = sourceCode.getFirstToken(body[i]);
                     const curLast = sourceCode.getLastToken(body[i]);
                     const nextFirst = sourceCode.getFirstToken(body[i + 1]);
-                    const isPadded = isPaddingBetweenTokens(curLast, nextFirst);
                     const isMulti = !astUtils.isTokenOnSameLine(curFirst, curLast);
                     const skip = !isMulti && options[1].exceptAfterSingleLine;
-
+                    const beforePadding = findLastConsecutiveTokenAfter(curLast, nextFirst, 1);
+                    const afterPadding = findFirstConsecutiveTokenBefore(nextFirst, curLast, 1);
+                    const isPadded = afterPadding.loc.start.line - beforePadding.loc.end.line > 1;
+                    const hasTokenInPadding = hasTokenOrCommentBetween(beforePadding, afterPadding);
+                    const curLineLastToken = findLastConsecutiveTokenAfter(curLast, nextFirst, 0);
 
                     if ((options[0] === "always" && !skip && !isPadded) ||
                         (options[0] === "never" && isPadded)) {
@@ -131,9 +117,12 @@ module.exports = {
                             node: body[i + 1],
                             messageId: isPadded ? "never" : "always",
                             fix(fixer) {
+                                if (hasTokenInPadding) {
+                                    return null;
+                                }
                                 return isPadded
-                                    ? fixer.replaceTextRange([curLast.range[1], nextFirst.range[0]], "\n")
-                                    : fixer.insertTextAfter(curLast, "\n");
+                                    ? fixer.replaceTextRange([beforePadding.range[1], afterPadding.range[0]], "\n")
+                                    : fixer.insertTextAfter(curLineLastToken, "\n");
                             }
                         });
                     }
diff --git a/lib/rules/no-multiple-empty-lines.js b/lib/rules/no-multiple-empty-lines.js
index f945cfeff..41e6be3a2 100644
--- a/lib/rules/no-multiple-empty-lines.js
+++ b/lib/rules/no-multiple-empty-lines.js
@@ -110,7 +110,7 @@ module.exports = {
                         if (lineNumber - lastLineNumber - 1 > maxAllowed) {
                             context.report({
                                 node,
-                                loc: { start: { line: lastLineNumber + 1, column: 0 }, end: { line: lineNumber, column: 0 } },
+                                loc: { start: { line: lastLineNumber + maxAllowed + 1, column: 0 }, end: { line: lineNumber, column: 0 } },
                                 message,
                                 data: { max: maxAllowed, pluralizedLines: maxAllowed === 1 ? "line" : "lines" },
                                 fix(fixer) {
diff --git a/lib/rules/no-restricted-imports.js b/lib/rules/no-restricted-imports.js
index bed9c2432..ec0696f99 100644
--- a/lib/rules/no-restricted-imports.js
+++ b/lib/rules/no-restricted-imports.js
@@ -72,14 +72,14 @@ module.exports = {
                 arrayOfStringsOrObjects,
                 {
                     type: "array",
-                    items: {
+                    items: [{
                         type: "object",
                         properties: {
                             paths: arrayOfStringsOrObjects,
                             patterns: arrayOfStrings
                         },
                         additionalProperties: false
-                    },
+                    }],
                     additionalItems: false
                 }
             ]
diff --git a/lib/rules/no-unsafe-negation.js b/lib/rules/no-unsafe-negation.js
index 5c8f569d7..a9c2ee74f 100644
--- a/lib/rules/no-unsafe-negation.js
+++ b/lib/rules/no-unsafe-negation.js
@@ -54,7 +54,8 @@ module.exports = {
             description: "disallow negating the left operand of relational operators",
             category: "Possible Errors",
             recommended: true,
-            url: "https://eslint.org/docs/rules/no-unsafe-negation"
+            url: "https://eslint.org/docs/rules/no-unsafe-negation",
+            suggestion: true
         },
 
         schema: [
@@ -69,9 +70,13 @@ module.exports = {
                 additionalProperties: false
             }
         ],
+
         fixable: null,
+
         messages: {
-            unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
+            unexpected: "Unexpected negating the left operand of '{{operator}}' operator.",
+            suggestNegatedExpression: "Negate '{{operator}}' expression instead of its left operand. This changes the current behavior.",
+            suggestParenthesisedNegation: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior."
         }
     },
 
@@ -82,10 +87,11 @@ module.exports = {
 
         return {
             BinaryExpression(node) {
-                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(node.operator);
+                const operator = node.operator;
+                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(operator);
 
                 if (
-                    (isInOrInstanceOfOperator(node.operator) || orderingRelationRuleApplies) &&
+                    (isInOrInstanceOfOperator(operator) || orderingRelationRuleApplies) &&
                     isNegation(node.left) &&
                     !astUtils.isParenthesised(sourceCode, node.left)
                 ) {
@@ -93,7 +99,26 @@ module.exports = {
                         node,
                         loc: node.left.loc,
                         messageId: "unexpected",
-                        data: { operator: node.operator }
+                        data: { operator },
+                        suggest: [
+                            {
+                                messageId: "suggestNegatedExpression",
+                                data: { operator },
+                                fix(fixer) {
+                                    const negationToken = sourceCode.getFirstToken(node.left);
+                                    const fixRange = [negationToken.range[1], node.range[1]];
+                                    const text = sourceCode.text.slice(fixRange[0], fixRange[1]);
+
+                                    return fixer.replaceTextRange(fixRange, `(${text})`);
+                                }
+                            },
+                            {
+                                messageId: "suggestParenthesisedNegation",
+                                fix(fixer) {
+                                    return fixer.replaceText(node.left, `(${sourceCode.getText(node.left)})`);
+                                }
+                            }
+                        ]
                     });
                 }
             }
diff --git a/lib/rules/prefer-numeric-literals.js b/lib/rules/prefer-numeric-literals.js
index 672d9bcaa..c352d88dc 100644
--- a/lib/rules/prefer-numeric-literals.js
+++ b/lib/rules/prefer-numeric-literals.js
@@ -15,6 +15,12 @@ const astUtils = require("./utils/ast-utils");
 // Helpers
 //------------------------------------------------------------------------------
 
+const radixMap = new Map([
+    [2, { system: "binary", literalPrefix: "0b" }],
+    [8, { system: "octal", literalPrefix: "0o" }],
+    [16, { system: "hexadecimal", literalPrefix: "0x" }]
+]);
+
 /**
  * Checks to see if a CallExpression's callee node is `parseInt` or
  * `Number.parseInt`.
@@ -54,49 +60,44 @@ module.exports = {
         },
 
         schema: [],
+
+        messages: {
+            useLiteral: "Use {{system}} literals instead of {{functionName}}()."
+        },
+
         fixable: "code"
     },
 
     create(context) {
         const sourceCode = context.getSourceCode();
 
-        const radixMap = {
-            2: "binary",
-            8: "octal",
-            16: "hexadecimal"
-        };
-
-        const prefixMap = {
-            2: "0b",
-            8: "0o",
-            16: "0x"
-        };
-
         //----------------------------------------------------------------------
         // Public
         //----------------------------------------------------------------------
 
         return {
 
-            CallExpression(node) {
-
-                // doesn't check parseInt() if it doesn't have a radix argument
-                if (node.arguments.length !== 2) {
-                    return;
-                }
+            "CallExpression[arguments.length=2]"(node) {
+                const [strNode, radixNode] = node.arguments,
+                    str = strNode.value,
+                    radix = radixNode.value;
+
+                if (
+                    strNode.type === "Literal" &&
+                    radixNode.type === "Literal" &&
+                    typeof str === "string" &&
+                    typeof radix === "number" &&
+                    radixMap.has(radix) &&
+                    isParseInt(node.callee)
+                ) {
 
-                // only error if the radix is 2, 8, or 16
-                const radixName = radixMap[node.arguments[1].value];
+                    const { system, literalPrefix } = radixMap.get(radix);
 
-                if (isParseInt(node.callee) &&
-                    radixName &&
-                    node.arguments[0].type === "Literal"
-                ) {
                     context.report({
                         node,
-                        message: "Use {{radixName}} literals instead of {{functionName}}().",
+                        messageId: "useLiteral",
                         data: {
-                            radixName,
+                            system,
                             functionName: sourceCode.getText(node.callee)
                         },
                         fix(fixer) {
@@ -104,9 +105,9 @@ module.exports = {
                                 return null;
                             }
 
-                            const replacement = `${prefixMap[node.arguments[1].value]}${node.arguments[0].value}`;
+                            const replacement = `${literalPrefix}${str}`;
 
-                            if (+replacement !== parseInt(node.arguments[0].value, node.arguments[1].value)) {
+                            if (+replacement !== parseInt(str, radix)) {
 
                                 /*
                                  * If the newly-produced literal would be invalid, (e.g. 0b1234),
diff --git a/lib/rules/require-atomic-updates.js b/lib/rules/require-atomic-updates.js
index 3912ad86c..bdd6d81eb 100644
--- a/lib/rules/require-atomic-updates.js
+++ b/lib/rules/require-atomic-updates.js
@@ -162,7 +162,7 @@ module.exports = {
         docs: {
             description: "disallow assignments that can lead to race conditions due to usage of `await` or `yield`",
             category: "Possible Errors",
-            recommended: true,
+            recommended: false,
             url: "https://eslint.org/docs/rules/require-atomic-updates"
         },
 
diff --git a/package.json b/package.json
index 5d0c0ba4a..ccb76c18b 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "6.7.2",
+  "version": "6.8.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index a1fd92ff9..8f3ed3125 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -175,6 +175,7 @@ rules:
     prefer-const: "error"
     prefer-numeric-literals: "error"
     prefer-promise-reject-errors: "error"
+    prefer-regex-literals: "error"
     prefer-rest-params: "error"
     prefer-spread: "error"
     prefer-template: "error"
diff --git a/packages/eslint-config-eslint/package.json b/packages/eslint-config-eslint/package.json
index 48bfb65f5..afbe4f558 100644
--- a/packages/eslint-config-eslint/package.json
+++ b/packages/eslint-config-eslint/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint-config-eslint",
-  "version": "5.0.1",
+  "version": "6.0.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "Default ESLint configuration for ESLint projects.",
   "scripts": {
diff --git a/webpack.config.js b/webpack.config.js
index 1630cef97..6a43ac755 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -3,8 +3,7 @@
 module.exports = {
     mode: "none",
     entry: {
-        eslint: ["core-js/stable", "regenerator-runtime/runtime", "./lib/linter/linter.js"],
-        espree: ["core-js/stable", "regenerator-runtime/runtime", "espree"]
+        eslint: ["core-js/stable", "regenerator-runtime/runtime", "./lib/linter/linter.js"]
     },
     output: {
         filename: "[name].js",


Test patch:
diff --git a/lib/rule-tester/rule-tester.js b/lib/rule-tester/rule-tester.js
index b4b3b2bec..44e01dadf 100644
--- a/lib/rule-tester/rule-tester.js
+++ b/lib/rule-tester/rule-tester.js
@@ -596,8 +596,10 @@ class RuleTester {
                         if (hasOwnProperty(error, "suggestions")) {
 
                             // Support asserting there are no suggestions
-                            if (!error.suggestions) {
-                                assert.strictEqual(message.suggestions, error.suggestions, `Error should have no suggestions on error with message: "${message.message}"`);
+                            if (!error.suggestions || (Array.isArray(error.suggestions) && error.suggestions.length === 0)) {
+                                if (Array.isArray(message.suggestions) && message.suggestions.length > 0) {
+                                    assert.fail(`Error should have no suggestions on error with message: "${message.message}"`);
+                                }
                             } else {
                                 assert.strictEqual(Array.isArray(message.suggestions), true, `Error should have an array of suggestions. Instead received "${message.suggestions}" on error with message: "${message.message}"`);
                                 assert.strictEqual(message.suggestions.length, error.suggestions.length, `Error should have ${error.suggestions.length} suggestions. Instead found ${message.suggestions.length} suggestions`);
diff --git a/tests/fixtures/config-file/cjs/.eslintrc.cjs b/tests/fixtures/config-file/cjs/.eslintrc.cjs
new file mode 100644
index 000000000..b3100591d
--- /dev/null
+++ b/tests/fixtures/config-file/cjs/.eslintrc.cjs
@@ -0,0 +1,5 @@
+module.exports = {
+    rules: {
+        semi: [2, "always"]
+    }
+};
diff --git a/tests/fixtures/unmatched-patterns/failing.js b/tests/fixtures/unmatched-patterns/failing.js
new file mode 100644
index 000000000..e24993ff6
--- /dev/null
+++ b/tests/fixtures/unmatched-patterns/failing.js
@@ -0,0 +1,3 @@
+var foo = "bar";
+if (foo) {
+    foo = "bar2";
diff --git a/tests/fixtures/unmatched-patterns/passing.js2 b/tests/fixtures/unmatched-patterns/passing.js2
new file mode 100644
index 000000000..425be7cea
--- /dev/null
+++ b/tests/fixtures/unmatched-patterns/passing.js2
@@ -0,0 +1,5 @@
+let foo = "bar";
+
+if (foo) {
+    foo = "bar2";
+}
diff --git a/tests/lib/cli-engine/config-array-factory.js b/tests/lib/cli-engine/config-array-factory.js
index 4f3ade1e6..1fb5661fb 100644
--- a/tests/lib/cli-engine/config-array-factory.js
+++ b/tests/lib/cli-engine/config-array-factory.js
@@ -171,6 +171,7 @@ describe("ConfigArrayFactory", () => {
     describe("'loadFile(filePath, options)' method should load a config file.", () => {
         const basicFiles = {
             "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }",
+            "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }",
             "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }",
             "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }",
             "legacy-yml/.eslintrc": "settings:\n  name: legacy-yml/.eslintrc",
@@ -288,6 +289,7 @@ describe("ConfigArrayFactory", () => {
     describe("'loadInDirectory(directoryPath, options)' method should load the config file of a directory.", () => {
         const basicFiles = {
             "js/.eslintrc.js": "exports.settings = { name: 'js/.eslintrc.js' }",
+            "cjs/.eslintrc.cjs": "exports.settings = { name: 'cjs/.eslintrc.cjs' }",
             "json/.eslintrc.json": "{ \"settings\": { \"name\": \"json/.eslintrc.json\" } }",
             "legacy-json/.eslintrc": "{ \"settings\": { \"name\": \"legacy-json/.eslintrc\" } }",
             "legacy-yml/.eslintrc": "settings:\n  name: legacy-yml/.eslintrc",
@@ -1497,6 +1499,7 @@ describe("ConfigArrayFactory", () => {
             "node_modules/eslint-plugin-invalid-parser/index.js": "exports.configs = { foo: { parser: 'nonexistent-parser' } }",
             "node_modules/eslint-plugin-invalid-config/index.js": "exports.configs = { foo: {} }",
             "js/.eslintrc.js": "module.exports = { rules: { semi: [2, 'always'] } };",
+            "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };",
             "json/.eslintrc.json": "{ \"rules\": { \"quotes\": [2, \"double\"] } }",
             "package-json/package.json": "{ \"eslintConfig\": { \"env\": { \"es6\": true } } }",
             "yaml/.eslintrc.yaml": "env:\n    browser: true"
@@ -1747,6 +1750,22 @@ describe("ConfigArrayFactory", () => {
             });
         });
 
+        it("should load information from a JavaScript file with a .cjs extension", () => {
+            const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
+                files: {
+                    "cjs/.eslintrc.cjs": "module.exports = { rules: { semi: [2, 'always'] } };"
+                }
+            });
+            const factory = new ConfigArrayFactory();
+            const config = load(factory, "cjs/.eslintrc.cjs");
+
+            assertConfig(config, {
+                rules: {
+                    semi: [2, "always"]
+                }
+            });
+        });
+
         it("should throw error when loading invalid JavaScript file", () => {
             const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
                 files: {
diff --git a/tests/lib/cli-engine/lint-result-cache.js b/tests/lib/cli-engine/lint-result-cache.js
index 7c5cc20a1..a3b6ee3ab 100644
--- a/tests/lib/cli-engine/lint-result-cache.js
+++ b/tests/lib/cli-engine/lint-result-cache.js
@@ -120,6 +120,35 @@ describe("LintResultCache", () => {
             lintResultsCache = new LintResultCache(cacheFileLocation);
         });
 
+        describe("when calculating the hashing", () => {
+            it("contains eslint version during hashing", () => {
+                const version = "eslint-=-version";
+                const NewLintResultCache = proxyquire("../../../lib/cli-engine/lint-result-cache.js", {
+                    "../../package.json": { version },
+                    "./hash": hashStub
+                });
+                const newLintResultCache = new NewLintResultCache(cacheFileLocation);
+
+                newLintResultCache.getCachedLintResults(filePath, fakeConfig);
+                assert.ok(hashStub.calledOnce);
+                assert.ok(hashStub.calledWithMatch(version));
+            });
+
+            it("contains node version during hashing", () => {
+                const version = "node-=-version";
+
+                sinon.stub(process, "version").value(version);
+                const NewLintResultCache = proxyquire("../../../lib/cli-engine/lint-result-cache.js", {
+                    "./hash": hashStub
+                });
+                const newLintResultCache = new NewLintResultCache(cacheFileLocation);
+
+                newLintResultCache.getCachedLintResults(filePath, fakeConfig);
+                assert.ok(hashStub.calledOnce);
+                assert.ok(hashStub.calledWithMatch(version));
+            });
+        });
+
         describe("When file is changed", () => {
             beforeEach(() => {
                 hashStub.returns(hashOfConfig);
diff --git a/tests/lib/cli.js b/tests/lib/cli.js
index e0f10d5ae..6af3b5c83 100644
--- a/tests/lib/cli.js
+++ b/tests/lib/cli.js
@@ -347,6 +347,74 @@ describe("cli", () => {
         });
     });
 
+    describe("when executing without no-error-on-unmatched-pattern flag", () => {
+        it("should throw an error on unmatched glob pattern", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const globPattern = "*.js3";
+
+            assert.throws(() => {
+                cli.execute(`"${filePath}/${globPattern}"`);
+            }, `No files matching '${filePath}/${globPattern}' were found.`);
+        });
+
+        it("should throw an error on unmatched --ext", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const extension = ".js3";
+
+            assert.throws(() => {
+                cli.execute(`--ext ${extension} ${filePath}`);
+            }, `No files matching '${filePath}' were found`);
+        });
+    });
+
+    describe("when executing with no-error-on-unmatched-pattern flag", () => {
+        it("should not throw an error on unmatched node glob syntax patterns", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`);
+
+            assert.strictEqual(exit, 0);
+        });
+
+        it("should not throw an error on unmatched --ext", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`);
+
+            assert.strictEqual(exit, 0);
+        });
+    });
+
+    describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
+        it("should not throw an error on multiple unmatched node glob syntax patterns", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`);
+
+            assert.strictEqual(exit, 0);
+        });
+
+        it("should still throw an error on when a matched pattern has lint errors", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`);
+
+            assert.strictEqual(exit, 1);
+        });
+    });
+
+    describe("when executing with no-error-on-unmatched-pattern flag and multiple --ext arguments", () => {
+        it("should not throw an error on multiple unmatched --ext arguments", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`);
+
+            assert.strictEqual(exit, 0);
+        });
+
+        it("should still throw an error on when a matched pattern has lint errors", () => {
+            const filePath = getFixturePath("unmatched-patterns");
+            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`);
+
+            assert.strictEqual(exit, 1);
+        });
+    });
+
     describe("when executing with help flag", () => {
         it("should print out help", () => {
             assert.strictEqual(cli.execute("-h"), 0);
diff --git a/tests/lib/rule-tester/rule-tester.js b/tests/lib/rule-tester/rule-tester.js
index 6ab341ccc..4abb053ab 100644
--- a/tests/lib/rule-tester/rule-tester.js
+++ b/tests/lib/rule-tester/rule-tester.js
@@ -1018,29 +1018,33 @@ describe("RuleTester", () => {
         });
 
         it("should support explicitly expecting no suggestions", () => {
-            ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/no-eval"), {
-                valid: [],
-                invalid: [{
-                    code: "eval('var foo');",
-                    errors: [{
-                        suggestions: void 0
-                    }]
-                }]
-            });
-        });
-
-        it("should fail when expecting no suggestions and there are suggestions", () => {
-            assert.throws(() => {
-                ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/suggestions").basic, {
+            [void 0, null, false, []].forEach(suggestions => {
+                ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/no-eval"), {
                     valid: [],
                     invalid: [{
-                        code: "var foo;",
+                        code: "eval('var foo');",
                         errors: [{
-                            suggestions: void 0
+                            suggestions
                         }]
                     }]
                 });
-            }, "Error should have no suggestions on error with message: \"Avoid using identifiers named 'foo'.\"");
+            });
+        });
+
+        it("should fail when expecting no suggestions and there are suggestions", () => {
+            [void 0, null, false, []].forEach(suggestions => {
+                assert.throws(() => {
+                    ruleTester.run("suggestions-basic", require("../../fixtures/testers/rule-tester/suggestions").basic, {
+                        valid: [],
+                        invalid: [{
+                            code: "var foo;",
+                            errors: [{
+                                suggestions
+                            }]
+                        }]
+                    });
+                }, "Error should have no suggestions on error with message: \"Avoid using identifiers named 'foo'.\"");
+            });
         });
 
         it("should fail when testing for suggestions that don't exist", () => {
diff --git a/tests/lib/rules/array-bracket-spacing.js b/tests/lib/rules/array-bracket-spacing.js
index 120c90501..33caf0889 100644
--- a/tests/lib/rules/array-bracket-spacing.js
+++ b/tests/lib/rules/array-bracket-spacing.js
@@ -190,7 +190,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -208,7 +210,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -217,7 +221,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 36
+                    column: 36,
+                    endLine: 1,
+                    endColumn: 37
                 }
             ]
         },
@@ -233,7 +239,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -242,7 +250,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 35
+                    column: 34,
+                    endLine: 1,
+                    endColumn: 35
                 }
             ]
         },
@@ -258,7 +268,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -267,7 +279,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 50
+                    column: 49,
+                    endLine: 1,
+                    endColumn: 50
                 }
             ]
         },
@@ -285,7 +299,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -294,7 +310,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 19
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
                 }
             ]
         },
@@ -310,7 +328,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 18
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 18
                 }
             ]
         },
@@ -326,7 +346,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -335,7 +357,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 17
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 18
                 }
             ]
         },
@@ -353,7 +377,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -369,7 +395,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 31
+                    column: 30,
+                    endLine: 1,
+                    endColumn: 31
                 }
             ]
         },
@@ -385,7 +413,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 34
+                    column: 33,
+                    endLine: 1,
+                    endColumn: 34
                 }
             ]
         },
@@ -401,7 +431,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -417,7 +449,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -426,7 +460,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 35
+                    column: 34,
+                    endLine: 1,
+                    endColumn: 35
                 }
             ]
         },
@@ -444,7 +480,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -453,7 +491,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 9
+                column: 9,
+                endLine: 1,
+                endColumn: 10
             }]
         },
         {
@@ -468,7 +508,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -483,7 +525,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -492,7 +536,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 12
+                column: 12,
+                endLine: 1,
+                endColumn: 13
             }]
         },
         {
@@ -507,7 +553,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 13
+                column: 13,
+                endLine: 1,
+                endColumn: 14
             }]
         },
         {
@@ -522,7 +570,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             },
             {
                 messageId: "missingSpaceBefore",
@@ -531,7 +581,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 14
+                column: 14,
+                endLine: 1,
+                endColumn: 15
             }]
         },
         {
@@ -546,7 +598,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -561,7 +615,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 5
+                column: 6,
+                endLine: 1,
+                endColumn: 7
             }]
         },
         {
@@ -576,7 +632,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 1
+                column: 2,
+                endLine: 1,
+                endColumn: 3
             }]
         },
         {
@@ -591,7 +649,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                 },
                 type: "ArrayPattern",
                 line: 1,
-                column: 15
+                column: 14,
+                endLine: 1,
+                endColumn: 15
             }]
         },
 
@@ -608,7 +668,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -617,7 +679,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 29
+                    column: 29,
+                    endLine: 1,
+                    endColumn: 30
                 }
             ]
         },
@@ -633,7 +697,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -651,7 +717,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -669,7 +737,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -678,7 +748,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 22
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 23
                 }
             ]
         },
@@ -694,7 +766,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 }
             ]
         },
@@ -710,7 +784,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 23
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
                 }
             ]
         },
@@ -728,7 +804,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -737,7 +815,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 24
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 24
                 }
             ]
         },
@@ -753,7 +833,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 23
+                    column: 22,
+                    endLine: 1,
+                    endColumn: 23
                 }
             ]
         },
@@ -769,7 +851,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 }
             ]
         },
@@ -785,7 +869,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 11
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
                 },
                 {
                     messageId: "unexpectedSpaceAfter",
@@ -794,7 +880,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 13
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 15
                 }
             ]
         },
@@ -810,7 +898,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 15
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 15
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -819,7 +909,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayExpression",
                     line: 1,
-                    column: 26
+                    column: 25,
+                    endLine: 1,
+                    endColumn: 26
                 }
             ]
         },
@@ -841,7 +933,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 2
+                    column: 3,
+                    endLine: 1,
+                    endColumn: 4
                 },
                 {
                     messageId: "unexpectedSpaceBefore",
@@ -850,7 +944,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 9
+                    column: 8,
+                    endLine: 1,
+                    endColumn: 9
                 }
             ]
         },
@@ -870,7 +966,9 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 2
+                    column: 2,
+                    endLine: 1,
+                    endColumn: 3
                 },
                 {
                     messageId: "missingSpaceBefore",
@@ -879,7 +977,152 @@ ruleTester.run("array-bracket-spacing", rule, {
                     },
                     type: "ArrayPattern",
                     line: 1,
-                    column: 7
+                    column: 7,
+                    endLine: 1,
+                    endColumn: 8
+                }
+            ]
+        },
+
+        // multiple spaces
+        {
+            code: "var arr = [  1, 2   ];",
+            output: "var arr = [1, 2];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 14
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 21
+                }
+            ]
+        },
+        {
+            code: "function f( [   a, b  ] ) {}",
+            output: "function f( [a, b] ) {}",
+            options: ["never"],
+            parserOptions: {
+                ecmaVersion: 6
+            },
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 17
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayPattern",
+                    line: 1,
+                    column: 21,
+                    endLine: 1,
+                    endColumn: 23
+                }
+            ]
+        },
+        {
+            code: "var arr = [ 1,\n   2   ];",
+            output: "var arr = [1,\n   2];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 2,
+                    column: 5,
+                    endLine: 2,
+                    endColumn: 8
+                }
+            ]
+        },
+        {
+            code: "var arr = [  1, [ 2, 3  ] ];",
+            output: "var arr = [1, [2, 3]];",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 14
+                },
+                {
+                    messageId: "unexpectedSpaceAfter",
+                    data: {
+                        tokenValue: "["
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 19
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 23,
+                    endLine: 1,
+                    endColumn: 25
+                },
+                {
+                    messageId: "unexpectedSpaceBefore",
+                    data: {
+                        tokenValue: "]"
+                    },
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 26,
+                    endLine: 1,
+                    endColumn: 27
                 }
             ]
         }
diff --git a/tests/lib/rules/brace-style.js b/tests/lib/rules/brace-style.js
index 4444863b6..70211608b 100644
--- a/tests/lib/rules/brace-style.js
+++ b/tests/lib/rules/brace-style.js
@@ -82,6 +82,22 @@ ruleTester.run("brace-style", rule, {
         { code: "if (foo) {}\nelse {}", options: ["allman", { allowSingleLine: true }] },
         { code: "try {  bar(); }\ncatch (e) { baz();  }", options: ["allman", { allowSingleLine: true }] },
         { code: "var foo = () => { return; }", options: ["allman", { allowSingleLine: true }], parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "if (foo) { baz(); } else {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "if (foo) { baz(); } else if (bar) {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "if (foo) { baz(); } else\nif (bar) {\n  boom();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
+        {
+            code: "try { somethingRisky(); } catch(e) {\n  handleError();\n}",
+            options: ["1tbs", { allowSingleLine: true }]
+        },
         {
             code: "if (tag === 1) fontstack.name = pbf.readString(); \nelse if (tag === 2) fontstack.range = pbf.readString(); \nelse if (tag === 3) {\n var glyph = pbf.readMessage(readGlyph, {});\n fontstack.glyphs[glyph.id] = glyph; \n}",
             options: ["1tbs"]
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index 9225b4341..3a4f0aa73 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -359,6 +359,16 @@ ruleTester.run("comma-dangle", rule, {
         },
 
         // trailing comma in functions
+        {
+            code: "function foo(a) {} ",
+            options: [{}],
+            parserOptions: { ecmaVersion: 8 }
+        },
+        {
+            code: "foo(a)",
+            options: [{}],
+            parserOptions: { ecmaVersion: 8 }
+        },
         {
             code: "function foo(a) {} ",
             options: [{ functions: "never" }],
diff --git a/tests/lib/rules/for-direction.js b/tests/lib/rules/for-direction.js
index 4dd4f8a99..a04b10e11 100644
--- a/tests/lib/rules/for-direction.js
+++ b/tests/lib/rules/for-direction.js
@@ -53,7 +53,13 @@ ruleTester.run("for-direction", rule, {
         "for(var i = 10; i >= 0; i %= 2){}",
         "for(var i = 0; i < MAX; i += STEP_SIZE);",
         "for(var i = 0; i < MAX; i -= STEP_SIZE);",
-        "for(var i = 10; i > 0; i += STEP_SIZE);"
+        "for(var i = 10; i > 0; i += STEP_SIZE);",
+
+        // other cond-expressions.
+        "for(var i = 0; i !== 10; i+=1){}",
+        "for(var i = 0; i === 10; i+=1){}",
+        "for(var i = 0; i == 10; i+=1){}",
+        "for(var i = 0; i != 10; i+=1){}"
     ],
     invalid: [
 
diff --git a/tests/lib/rules/indent.js b/tests/lib/rules/indent.js
index 249f9bc91..93ebb2824 100644
--- a/tests/lib/rules/indent.js
+++ b/tests/lib/rules/indent.js
@@ -2097,6 +2097,86 @@ ruleTester.run("indent", rule, {
             `,
             options: [2]
         },
+        {
+            code: unIndent`
+              condition
+                ? () => {
+                  return true
+                }
+                : condition2
+                  ? () => {
+                    return true
+                  }
+                  : () => {
+                    return false
+                  }
+            `,
+            options: [2]
+        },
+        {
+            code: unIndent`
+              condition
+                ? () => {
+                  return true
+                }
+                : condition2
+                  ? () => {
+                    return true
+                  }
+                  : () => {
+                    return false
+                  }
+            `,
+            options: [2, { offsetTernaryExpressions: false }]
+        },
+        {
+            code: unIndent`
+              condition
+                ? () => {
+                    return true
+                  }
+                : condition2
+                  ? () => {
+                      return true
+                    }
+                  : () => {
+                      return false
+                    }
+            `,
+            options: [2, { offsetTernaryExpressions: true }]
+        },
+        {
+            code: unIndent`
+              condition
+                  ? () => {
+                          return true
+                      }
+                  : condition2
+                      ? () => {
+                              return true
+                          }
+                      : () => {
+                              return false
+                          }
+            `,
+            options: [4, { offsetTernaryExpressions: true }]
+        },
+        {
+            code: unIndent`
+              condition
+              \t? () => {
+              \t\t\treturn true
+              \t\t}
+              \t: condition2
+              \t\t? () => {
+              \t\t\t\treturn true
+              \t\t\t}
+              \t\t: () => {
+              \t\t\t\treturn false
+              \t\t\t}
+            `,
+            options: ["tab", { offsetTernaryExpressions: true }]
+        },
         unIndent`
             [
                 foo ?
@@ -7705,6 +7785,88 @@ ruleTester.run("indent", rule, {
             `,
             errors: expectedErrors([5, 4, 8, "Identifier"])
         },
+        {
+            code: unIndent`
+              condition
+              ? () => {
+              return true
+              }
+              : condition2
+              ? () => {
+              return true
+              }
+              : () => {
+              return false
+              }
+            `,
+            output: unIndent`
+              condition
+                ? () => {
+                    return true
+                  }
+                : condition2
+                  ? () => {
+                      return true
+                    }
+                  : () => {
+                      return false
+                    }
+            `,
+            options: [2, { offsetTernaryExpressions: true }],
+            errors: expectedErrors([
+                [2, 2, 0, "Punctuator"],
+                [3, 6, 0, "Keyword"],
+                [4, 4, 0, "Punctuator"],
+                [5, 2, 0, "Punctuator"],
+                [6, 4, 0, "Punctuator"],
+                [7, 8, 0, "Keyword"],
+                [8, 6, 0, "Punctuator"],
+                [9, 4, 0, "Punctuator"],
+                [10, 8, 0, "Keyword"],
+                [11, 6, 0, "Punctuator"]
+            ])
+        },
+        {
+            code: unIndent`
+              condition
+              ? () => {
+              return true
+              }
+              : condition2
+              ? () => {
+              return true
+              }
+              : () => {
+              return false
+              }
+            `,
+            output: unIndent`
+              condition
+                ? () => {
+                  return true
+                }
+                : condition2
+                  ? () => {
+                    return true
+                  }
+                  : () => {
+                    return false
+                  }
+            `,
+            options: [2, { offsetTernaryExpressions: false }],
+            errors: expectedErrors([
+                [2, 2, 0, "Punctuator"],
+                [3, 4, 0, "Keyword"],
+                [4, 2, 0, "Punctuator"],
+                [5, 2, 0, "Punctuator"],
+                [6, 4, 0, "Punctuator"],
+                [7, 6, 0, "Keyword"],
+                [8, 4, 0, "Punctuator"],
+                [9, 4, 0, "Punctuator"],
+                [10, 6, 0, "Keyword"],
+                [11, 4, 0, "Punctuator"]
+            ])
+        },
         {
 
             /*
diff --git a/tests/lib/rules/key-spacing.js b/tests/lib/rules/key-spacing.js
index a9ed53374..29bbbe857 100644
--- a/tests/lib/rules/key-spacing.js
+++ b/tests/lib/rules/key-spacing.js
@@ -757,6 +757,141 @@ ruleTester.run("key-spacing", rule, {
             }
         }],
         parserOptions: { ecmaVersion: 6 }
+    }, {
+        code: [
+            "var obj = {",
+            "    foo : 1, 'bar' : 2, baz : 3, longlonglong : 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            multiLine: {
+                beforeColon: true,
+                afterColon: true,
+                align: "colon"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo: 1, 'bar': 2, baz: 3",
+            "}"
+        ].join("\n"),
+        options: [{
+            multiLine: {
+                align: "value"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo: 1",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            multiLine: {
+                align: "value"
+            }
+        }]
+    }, {
+        code: [
+            "foo({",
+            "    bar: 1",
+            "})"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }]
+    }, {
+        code: "var obj = { foo:1, 'bar':2, baz:3, longlonglong:4 }",
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo         : 1,",
+            "    'bar'       : 2, baz         : 3, longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo:          1,",
+            "    'bar':        2, baz:          3, longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "value"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo         : 1,",
+            "    'bar'       : 2, baz         : 3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo:          1,",
+            "    'bar':        2, baz:          3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "value"
+            }
+        }]
     }],
 
     invalid: [{
@@ -1769,5 +1904,206 @@ ruleTester.run("key-spacing", rule, {
             { messageId: "missingKey", data: { computed: "", key: "foo" }, line: 1, column: 7, type: "Identifier" },
             { messageId: "missingValue", data: { computed: "", key: "foo" }, line: 1, column: 19, type: "Identifier" }
         ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo:1, 'bar':2, baz:3",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo : 1, 'bar' : 2, baz : 3",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            multiLine: {
+                beforeColon: true,
+                afterColon: true,
+                align: "colon"
+            }
+        }],
+        errors: [
+            { messageId: "missingKey", data: { computed: "", key: "foo" }, line: 2, column: 5, type: "Identifier" },
+            { messageId: "missingValue", data: { computed: "", key: "foo" }, line: 2, column: 9, type: "Literal" },
+            { messageId: "missingKey", data: { computed: "", key: "bar" }, line: 2, column: 12, type: "Literal" },
+            { messageId: "missingValue", data: { computed: "", key: "bar" }, line: 2, column: 18, type: "Literal" },
+            { messageId: "missingKey", data: { computed: "", key: "baz" }, line: 2, column: 21, type: "Identifier" },
+            { messageId: "missingValue", data: { computed: "", key: "baz" }, line: 2, column: 25, type: "Literal" }
+        ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo : 1, 'bar' : 2, baz : 3, longlonglong : 4",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo: 1, 'bar': 2, baz: 3, longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            multiLine: {
+                align: "value"
+            }
+        }],
+        errors: [
+            { messageId: "extraKey", data: { computed: "", key: "foo" }, line: 2, column: 5, type: "Identifier" },
+            { messageId: "extraKey", data: { computed: "", key: "bar" }, line: 2, column: 14, type: "Literal" },
+            { messageId: "extraKey", data: { computed: "", key: "baz" }, line: 2, column: 25, type: "Identifier" },
+            { messageId: "extraKey", data: { computed: "", key: "longlonglong" }, line: 2, column: 34, type: "Identifier" }
+        ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo:1",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo: 1",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            multiLine: {
+                align: "value"
+            }
+        }],
+        errors: [
+            { messageId: "missingValue", data: { computed: "", key: "foo" }, line: 2, column: 9, type: "Literal" }
+        ]
+    }, {
+        code: [
+            "foo({",
+            "    bar:1",
+            "})"
+        ].join("\n"),
+        output: [
+            "foo({",
+            "    bar: 1",
+            "})"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }],
+        errors: [
+            { messageId: "missingValue", data: { computed: "", key: "bar" }, line: 2, column: 9, type: "Literal" }
+        ]
+    }, {
+        code: "var obj = { foo: 1, 'bar': 2, baz :3, longlonglong :4 }",
+        output: "var obj = { foo:1, 'bar':2, baz:3, longlonglong:4 }",
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }],
+        errors: [
+            { messageId: "extraValue", data: { computed: "", key: "foo" }, line: 1, column: 18, type: "Literal" },
+            { messageId: "extraValue", data: { computed: "", key: "bar" }, line: 1, column: 28, type: "Literal" },
+            { messageId: "extraKey", data: { computed: "", key: "baz" }, line: 1, column: 31, type: "Identifier" },
+            { messageId: "extraKey", data: { computed: "", key: "longlonglong" }, line: 1, column: 39, type: "Identifier" }
+        ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo: 1,",
+            "    'bar': 2, baz: 3, longlonglong: 4",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo         : 1,",
+            "    'bar'       : 2, baz         : 3, longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }],
+        errors: [
+            { messageId: "missingKey", data: { computed: "", key: "foo" }, line: 2, column: 5, type: "Identifier" },
+            { messageId: "missingKey", data: { computed: "", key: "bar" }, line: 3, column: 5, type: "Literal" },
+            { messageId: "missingKey", data: { computed: "", key: "baz" }, line: 3, column: 15, type: "Identifier" }
+        ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo : 1,",
+            "    'bar' : 2, baz : 3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo         : 1,",
+            "    'bar'       : 2, baz         : 3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "colon"
+            }
+        }],
+        errors: [
+            { messageId: "missingKey", data: { computed: "", key: "foo" }, line: 2, column: 5, type: "Identifier" },
+            { messageId: "missingKey", data: { computed: "", key: "bar" }, line: 3, column: 5, type: "Literal" },
+            { messageId: "missingKey", data: { computed: "", key: "baz" }, line: 3, column: 16, type: "Identifier" }
+        ]
+    }, {
+        code: [
+            "var obj = {",
+            "    foo: 1,",
+            "    'bar': 2, baz: 3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        output: [
+            "var obj = {",
+            "    foo:          1,",
+            "    'bar':        2, baz:          3,",
+            "    longlonglong: 4",
+            "}"
+        ].join("\n"),
+        options: [{
+            singleLine: {
+                beforeColon: false,
+                afterColon: false
+            },
+            align: {
+                on: "value"
+            }
+        }],
+        errors: [
+            { messageId: "missingValue", data: { computed: "", key: "foo" }, line: 2, column: 10, type: "Literal" },
+            { messageId: "missingValue", data: { computed: "", key: "bar" }, line: 3, column: 12, type: "Literal" },
+            { messageId: "missingValue", data: { computed: "", key: "baz" }, line: 3, column: 20, type: "Literal" }
+        ]
     }]
 });
diff --git a/tests/lib/rules/lines-between-class-members.js b/tests/lib/rules/lines-between-class-members.js
index d1aa8607c..e4b1c0c09 100644
--- a/tests/lib/rules/lines-between-class-members.js
+++ b/tests/lib/rules/lines-between-class-members.js
@@ -40,6 +40,9 @@ ruleTester.run("lines-between-class-members", rule, {
         "class A{ foo() {}\n/* a */ /* b */\n\nbar() {}}",
         "class A{ foo() {}/* a */ \n\n /* b */bar() {}}",
 
+        "class A {\nfoo() {}\n/* comment */;\n;\n\nbar() {}\n}",
+        "class A {\nfoo() {}\n// comment\n\n;\n;\nbar() {}\n}",
+
         "class foo{ bar(){}\n\n;;baz(){}}",
         "class foo{ bar(){};\n\nbaz(){}}",
 
@@ -73,6 +76,71 @@ ruleTester.run("lines-between-class-members", rule, {
             output: "class foo{ bar(){\n}\n\nbaz(){}}",
             options: ["always", { exceptAfterSingleLine: true }],
             errors: [alwaysError]
+        }, {
+            code: "class foo{ bar(){\n}\n/* comment */\nbaz(){}}",
+            output: "class foo{ bar(){\n}\n\n/* comment */\nbaz(){}}",
+            options: ["always", { exceptAfterSingleLine: true }],
+            errors: [alwaysError]
+        }, {
+            code: "class foo{ bar(){}\n\n// comment\nbaz(){}}",
+            output: "class foo{ bar(){}\n// comment\nbaz(){}}",
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n\n/* comment */\nbaz(){}}",
+            output: "class foo{ bar(){}\n/* comment */\nbaz(){}}",
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n/* comment-1 */\n\n/* comment-2 */\nbaz(){}}",
+            output: "class foo{ bar(){}\n/* comment-1 */\n/* comment-2 */\nbaz(){}}",
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n\n/* comment */\n\nbaz(){}}",
+            output: null,
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n\n// comment\n\nbaz(){}}",
+            output: null,
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n/* comment-1 */\n\n/* comment-2 */\n\n/* comment-3 */\nbaz(){}}",
+            output: null,
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class foo{ bar(){}\n/* comment-1 */\n\n;\n\n/* comment-3 */\nbaz(){}}",
+            output: null,
+            options: ["never"],
+            errors: [neverError]
+        }, {
+            code: "class A {\nfoo() {}// comment\n;\n/* comment */\nbar() {}\n}",
+            output: "class A {\nfoo() {}// comment\n\n;\n/* comment */\nbar() {}\n}",
+            options: ["always"],
+            errors: [alwaysError]
+        }, {
+            code: "class A {\nfoo() {}\n/* comment */;\n;\n/* comment */\nbar() {}\n}",
+            output: "class A {\nfoo() {}\n\n/* comment */;\n;\n/* comment */\nbar() {}\n}",
+            options: ["always"],
+            errors: [alwaysError]
+        }, {
+            code: "class foo{ bar(){};\nbaz(){}}",
+            output: "class foo{ bar(){};\n\nbaz(){}}",
+            options: ["always"],
+            errors: [alwaysError]
+        }, {
+            code: "class foo{ bar(){} // comment \nbaz(){}}",
+            output: "class foo{ bar(){} // comment \n\nbaz(){}}",
+            options: ["always"],
+            errors: [alwaysError]
+        }, {
+            code: "class A {\nfoo() {}\n/* comment */;\n;\nbar() {}\n}",
+            output: "class A {\nfoo() {}\n\n/* comment */;\n;\nbar() {}\n}",
+            options: ["always"],
+            errors: [alwaysError]
         }
     ]
 });
diff --git a/tests/lib/rules/no-multiple-empty-lines.js b/tests/lib/rules/no-multiple-empty-lines.js
index 5c51dd811..7b14f75ae 100644
--- a/tests/lib/rules/no-multiple-empty-lines.js
+++ b/tests/lib/rules/no-multiple-empty-lines.js
@@ -316,6 +316,32 @@ ruleTester.run("no-multiple-empty-lines", rule, {
             output: "foo\n",
             options: [{ max: 1, maxEOF: 0 }],
             errors: [getExpectedErrorEOF(0)]
+        },
+        {
+
+            // https://github.com/eslint/eslint/pull/12594
+            code: "var a;\n\n\n\n\nvar b;",
+            output: "var a;\n\nvar b;",
+            options: [{ max: 1 }],
+            errors: [{
+                message: "More than 1 blank line not allowed.",
+                type: "Program",
+                line: 3,
+                column: 1
+            }]
+        },
+        {
+
+            // https://github.com/eslint/eslint/pull/12594
+            code: "var a;\n\n\n\n\nvar b;",
+            output: "var a;\n\n\nvar b;",
+            options: [{ max: 2 }],
+            errors: [{
+                message: "More than 2 blank lines not allowed.",
+                type: "Program",
+                line: 4,
+                column: 1
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-param-reassign.js b/tests/lib/rules/no-param-reassign.js
index 5bb70e6aa..6985cabb8 100644
--- a/tests/lib/rules/no-param-reassign.js
+++ b/tests/lib/rules/no-param-reassign.js
@@ -91,6 +91,14 @@ ruleTester.run("no-param-reassign", rule, {
             code: "function foo(a) { for (bar of baz) a.b; }",
             options: [{ props: true }],
             parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo(bar, baz) { bar.a = true; baz.b = false; }",
+            options: [{
+                props: true,
+                ignorePropertyModificationsForRegex: ["^(foo|bar)$"],
+                ignorePropertyModificationsFor: ["baz"]
+            }]
         }
     ],
 
diff --git a/tests/lib/rules/no-restricted-imports.js b/tests/lib/rules/no-restricted-imports.js
index ac97bc137..15ee089b2 100644
--- a/tests/lib/rules/no-restricted-imports.js
+++ b/tests/lib/rules/no-restricted-imports.js
@@ -20,6 +20,7 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6, sourceType:
 
 ruleTester.run("no-restricted-imports", rule, {
     valid: [
+        "import os from \"os\";",
         { code: "import os from \"os\";", options: ["osx"] },
         { code: "import fs from \"fs\";", options: ["crypto"] },
         { code: "import path from \"path\";", options: ["crypto", "stream", "os"] },
diff --git a/tests/lib/rules/no-unsafe-negation.js b/tests/lib/rules/no-unsafe-negation.js
index 9493bbb72..23e6cd5ce 100644
--- a/tests/lib/rules/no-unsafe-negation.js
+++ b/tests/lib/rules/no-unsafe-negation.js
@@ -17,27 +17,6 @@ const rule = require("../../../lib/rules/no-unsafe-negation"),
 //------------------------------------------------------------------------------
 
 const ruleTester = new RuleTester();
-const unexpectedInError = { messageId: "unexpected", data: { operator: "in" } };
-const unexpectedInstanceofError = {
-    messageId: "unexpected",
-    data: { operator: "instanceof" }
-};
-const unexpectedLessThanOperatorError = {
-    messageId: "unexpected",
-    data: { operator: "<" }
-};
-const unexpectedMoreThanOperatorError = {
-    messageId: "unexpected",
-    data: { operator: ">" }
-};
-const unexpectedMoreThanOrEqualOperatorError = {
-    messageId: "unexpected",
-    data: { operator: ">=" }
-};
-const unexpectedLessThanOrEqualOperatorError = {
-    messageId: "unexpected",
-    data: { operator: "<=" }
-};
 
 ruleTester.run("no-unsafe-negation", rule, {
     valid: [
@@ -83,52 +62,194 @@ ruleTester.run("no-unsafe-negation", rule, {
     invalid: [
         {
             code: "!a in b",
-            errors: [unexpectedInError]
+            errors: [{
+                message: "Unexpected negating the left operand of 'in' operator.",
+                suggestions: [
+                    {
+                        desc: "Negate 'in' expression instead of its left operand. This changes the current behavior.",
+                        output: "!(a in b)"
+                    },
+                    {
+                        desc: "Wrap negation in '()' to make the intention explicit. This preserves the current behavior.",
+                        output: "(!a) in b"
+                    }
+                ]
+            }]
         },
         {
             code: "(!a in b)",
-            errors: [unexpectedInError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "in" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "(!(a in b))"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "((!a) in b)"
+                    }
+                ]
+            }]
         },
         {
             code: "!(a) in b",
-            errors: [unexpectedInError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "in" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!((a) in b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!(a)) in b"
+                    }
+                ]
+            }]
         },
         {
             code: "!a instanceof b",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!(a instanceof b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!a) instanceof b"
+                    }
+                ]
+            }]
         },
         {
             code: "(!a instanceof b)",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "(!(a instanceof b))"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "((!a) instanceof b)"
+                    }
+                ]
+            }]
         },
         {
             code: "!(a) instanceof b",
-            errors: [unexpectedInstanceofError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "instanceof" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!((a) instanceof b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(!(a)) instanceof b"
+                    }
+                ]
+            }]
         },
         {
             code: "if (! a < b) {}",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "if (!( a < b)) {}"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "if ((! a) < b) {}"
+                    }
+                ]
+            }]
         },
         {
             code: "while (! a > b) {}",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedMoreThanOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: ">" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "while (!( a > b)) {}"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "while ((! a) > b) {}"
+                    }
+                ]
+            }]
         },
         {
             code: "foo = ! a <= b;",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "foo = !( a <= b);"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "foo = (! a) <= b;"
+                    }
+                ]
+            }]
         },
         {
             code: "foo = ! a >= b;",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedMoreThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: ">=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "foo = !( a >= b);"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "foo = (! a) >= b;"
+                    }
+                ]
+            }]
         },
         {
             code: "! a <= b",
             options: [{ enforceForOrderingRelations: true }],
-            errors: [unexpectedLessThanOrEqualOperatorError]
+            errors: [{
+                messageId: "unexpected",
+                data: { operator: "<=" },
+                suggestions: [
+                    {
+                        messageId: "suggestNegatedExpression",
+                        output: "!( a <= b)"
+                    },
+                    {
+                        messageId: "suggestParenthesisedNegation",
+                        output: "(! a) <= b"
+                    }
+                ]
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/prefer-numeric-literals.js b/tests/lib/rules/prefer-numeric-literals.js
index ddd6e36c8..4d3037f44 100644
--- a/tests/lib/rules/prefer-numeric-literals.js
+++ b/tests/lib/rules/prefer-numeric-literals.js
@@ -31,7 +31,28 @@ ruleTester.run("prefer-numeric-literals", rule, {
         "parseInt(foo);",
         "parseInt(foo, 2);",
         "Number.parseInt(foo);",
-        "Number.parseInt(foo, 2);"
+        "Number.parseInt(foo, 2);",
+        "parseInt(11, 2);",
+        "Number.parseInt(1, 8);",
+        "parseInt(1e5, 16);",
+        "parseInt('11', '2');",
+        "Number.parseInt('11', '8');",
+        {
+            code: "parseInt('11', 2n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "Number.parseInt('11', 8n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "parseInt('11', 16n);",
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "parseInt(1n, 2);",
+            parserOptions: { ecmaVersion: 2020 }
+        }
     ],
     invalid: [
         {
diff --git a/tests/lib/rules/yield-star-spacing.js b/tests/lib/rules/yield-star-spacing.js
index 0665f648e..9c8aaff95 100644
--- a/tests/lib/rules/yield-star-spacing.js
+++ b/tests/lib/rules/yield-star-spacing.js
@@ -137,6 +137,24 @@ ruleTester.run("yield-star-spacing", rule, {
         {
             code: "function *foo(){ var result = yield*foo(); }",
             options: ["neither"]
+        },
+
+        // object option
+        {
+            code: "function *foo(){ yield* foo; }",
+            options: [{ before: false, after: true }]
+        },
+        {
+            code: "function *foo(){ yield *foo; }",
+            options: [{ before: true, after: false }]
+        },
+        {
+            code: "function *foo(){ yield * foo; }",
+            options: [{ before: true, after: true }]
+        },
+        {
+            code: "function *foo(){ yield*foo; }",
+            options: [{ before: false, after: false }]
         }
     ],
 
@@ -227,6 +245,32 @@ ruleTester.run("yield-star-spacing", rule, {
             output: "function *foo(){ yield*foo; }",
             options: ["neither"],
             errors: [unexpectedBeforeError, unexpectedAfterError]
+        },
+
+        // object option
+        {
+            code: "function *foo(){ yield*foo; }",
+            output: "function *foo(){ yield* foo; }",
+            options: [{ before: false, after: true }],
+            errors: [missingAfterError]
+        },
+        {
+            code: "function *foo(){ yield * foo; }",
+            output: "function *foo(){ yield *foo; }",
+            options: [{ before: true, after: false }],
+            errors: [unexpectedAfterError]
+        },
+        {
+            code: "function *foo(){ yield*foo; }",
+            output: "function *foo(){ yield * foo; }",
+            options: [{ before: true, after: true }],
+            errors: [missingBeforeError, missingAfterError]
+        },
+        {
+            code: "function *foo(){ yield * foo; }",
+            output: "function *foo(){ yield*foo; }",
+            options: [{ before: false, after: false }],
+            errors: [unexpectedBeforeError, unexpectedAfterError]
         }
     ]
 
diff --git a/tests/lib/shared/config-validator.js b/tests/lib/shared/config-validator.js
index 1c4cfe895..95976fc9f 100644
--- a/tests/lib/shared/config-validator.js
+++ b/tests/lib/shared/config-validator.js
@@ -114,6 +114,7 @@ describe("Validator", () => {
         it("should do nothing with a valid eslint config", () => {
             validator.validate(
                 {
+                    $schema: "http://json.schemastore.org/eslintrc",
                     root: true,
                     globals: { globalFoo: "readonly" },
                     parser: "parserFoo",