Repository: eslint/eslint
Pull request #12470 (2019-10-21 00:38:44)

Fix: no-cond-assign with `always` option reports switch case clauses
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[X] Bug fix

This bug fix can produce only fewer warnings.

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

**Tell us about your environment**

* **ESLint Version:**  6.5.1
* **Node Version:** 10.16.0
* **npm Version:** 6.9.0

**What parser (default, Babel-ESLint, etc.) are you using?**

default

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
module.exports = {
  parserOptions: {
    ecmaVersion: 2015,
  }
};
```

</details>

**What did you do? Please include the actual source code causing the issue.**

[Online Demo Link](https://eslint.org/demo#eyJ0ZXh0IjoiLyogZXNsaW50IG5vLWNvbmQtYXNzaWduOiBbXCJlcnJvclwiLCBcImFsd2F5c1wiXSAqL1xuXG5zd2l0Y2ggKGZvbykge1xuICAgIGNhc2UgYSA9IGI6IFxuICAgICAgICBicmVhaztcbn0iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjUsInNvdXJjZVR5cGUiOiJzY3JpcHQiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

```js
/* eslint no-cond-assign: ["error", "always"] */

switch (foo) {
    case a = b: 
        break;
}
```

**What did you expect to happen?**

No errors. Per the documentation, this rule doesn't target switch case clauses.

**What actually happened? Please include the actual, raw output from ESLint.**

```
 4:5  error  Unexpected assignment within SwitchCase  no-cond-assign
```

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

Check parent statement's type.

**Is there anything you'd like reviewers to focus on?**

This test case was already valid:

```js
{ code: "switch (foo) { case a = b: bar(); }", options: ["except-parens"] }
```

These test cases were invalid, that's the bug fixed by this PR:

```js
{ code: "switch (foo) { case a = b: bar(); }", options: ["always"] },
{ code: "switch (foo) { case baz + (a = b): bar(); }", options: ["always"] }
```

This test case was added for regression, as there were no test cases for `always` with `ConditionalExpression`. It was already invalid:

```js
{ code: "var x; var b = x && (y = 0) ? 1 : 0;", options: ["always"], errors: [{ messageId: "unexpected", type: "ConditionalExpression" }] },
```

I'll open a separate issue for conditional expressions.


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0e7d5181c..dd533de3e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,16 +26,24 @@ jobs:
     strategy:
       matrix:
         os: [ubuntu-latest, windows-latest, macOS-latest]
-        node: [8.x, 10.x, 12.x]
+        node: [13.x, 12.x, 10.x, 8.x, "8.10.0"]
         exclude:
+        - os: windows-latest
+          node: "8.10.0"
         - os: windows-latest
           node: 8.x
         - os: windows-latest
           node: 10.x
+        - os: windows-latest
+          node: 13.x
+        - os: macOS-latest
+          node: "8.10.0"
         - os: macOS-latest
           node: 8.x
         - os: macOS-latest
           node: 10.x
+        - os: macOS-latest
+          node: 13.x
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1568a984d..438b6ca28 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,57 @@
+v6.6.0 - October 25, 2019
+
+* [`39dfe08`](https://github.com/eslint/eslint/commit/39dfe0880fa934e287e8ea1f7b56d5cba8d43765) Update: false positives in function-call-argument-newline (fixes #12123) (#12280) (Scott O'Hara)
+* [`4d84210`](https://github.com/eslint/eslint/commit/4d842105c9c82026be668d7425213138903d4d41) Update: improve report location for no-trailing-spaces (fixes #12315) (#12477) (Milos Djermanovic)
+* [`c6a7745`](https://github.com/eslint/eslint/commit/c6a7745a1371a85932bfae5fec039d1b6fcfc128) Update: no-trailing-spaces false negatives after comments (fixes #12479) (#12480) (Milos Djermanovic)
+* [`0bffe95`](https://github.com/eslint/eslint/commit/0bffe953d2752dd2d3045f2f8771c96b6cee8fc4) Fix: no-misleading-character-class crash on invalid regex (fixes #12169) (#12347) (Milos Djermanovic)
+* [`c6a9a3b`](https://github.com/eslint/eslint/commit/c6a9a3bc58b69dbf9be9cd09b0283c081ca211e7) Update: Add enforceForIndexOf option to use-isnan (fixes #12207) (#12379) (Milos Djermanovic)
+* [`364877b`](https://github.com/eslint/eslint/commit/364877b2504e8f7ece04770b93d517e2f27458d0) Update: measure plugin loading time and output in debug message (#12395) (Victor Homyakov)
+* [`1744fab`](https://github.com/eslint/eslint/commit/1744faba3c93c869f7dbbf0a704d32e2692d6856) Fix: operator-assignment removes and duplicates comments (#12485) (Milos Djermanovic)
+* [`52ca11a`](https://github.com/eslint/eslint/commit/52ca11a66ab6c2fb5a71d8b9869482f14f98cb9d) Fix: operator-assignment invalid autofix with adjacent tokens (#12483) (Milos Djermanovic)
+* [`0f6d0dc`](https://github.com/eslint/eslint/commit/0f6d0dcdf5adc30079a7379bbf605a4ef3887a85) Fix: CLIEngine#addPlugin reset lastConfigArrays (fixes #12425) (#12468) (Toru Nagashima)
+* [`923a8cb`](https://github.com/eslint/eslint/commit/923a8cb752b8dee1e622c5fd36f3f53288e30602) Chore: Fix lint failure in JSDoc comment (#12489) (Brandon Mills)
+* [`aac3be4`](https://github.com/eslint/eslint/commit/aac3be435cccc241781150fcac728df04d086fa8) Update: Add ignored prop regex no-param-reassign (#11275) (Luke Bennett)
+* [`e5382d6`](https://github.com/eslint/eslint/commit/e5382d6e4eb1344f537b6f107535269e9939fcb8) Chore: Remove unused parameter in dot-location (#12464) (Milos Djermanovic)
+* [`49faefb`](https://github.com/eslint/eslint/commit/49faefbee3fc7daaf2482d9d7d23513d6ffda9e8) Fix: no-obj-calls false positive (fixes #12437) (#12467) (Toru Nagashima)
+* [`b3dbd96`](https://github.com/eslint/eslint/commit/b3dbd9657bbeac6571111a4429b03fc085ba6655) Fix: problematic installation issue (fixes #11018) (#12309) (Toru Nagashima)
+* [`cd7c29b`](https://github.com/eslint/eslint/commit/cd7c29b17085c14c9cf6345201c72a192c0d0e0c) Sponsors: Sync README with website (ESLint Jenkins)
+* [`8233873`](https://github.com/eslint/eslint/commit/8233873b8e5facd80ab7b172bff1e896a9c5fd39) Docs: Add note about Node.js requiring SSL support (fixes #11413) (#12475) (Nicholas C. Zakas)
+* [`89e8aaf`](https://github.com/eslint/eslint/commit/89e8aafcc622a4763bed6b9d62f148ef95798f38) Fix: improve report location for no-tabs (#12471) (Milos Djermanovic)
+* [`7dffe48`](https://github.com/eslint/eslint/commit/7dffe482d646d4e5f94fa87a22f3b5b2e0a4b189) Update: Enable function string option in comma-dangle (fixes #12058) (#12462) (YeonJuan)
+* [`e15e1f9`](https://github.com/eslint/eslint/commit/e15e1f933f287d274a726e7f0f0a1dd80f0964af) Docs: fix doc for no-unneeded-ternary rule (fixes #12098) (#12410) (Sam Rae)
+* [`b1dc58f`](https://github.com/eslint/eslint/commit/b1dc58f0a717cb3d19300c845ca23a21ceb610d3) Sponsors: Sync README with website (ESLint Jenkins)
+* [`61749c9`](https://github.com/eslint/eslint/commit/61749c94bd8a2ebcdfb89e0cd48c4a029a945079) Chore: Provide debug log for parser errors (#12474) (Brad Zacher)
+* [`7c8bbe0`](https://github.com/eslint/eslint/commit/7c8bbe0391944e1f92e083a04715bf4b3fe6be5d) Update: enforceForOrderingRelations no-unsafe-negation (fixes #12163) (#12414) (Sam Rae)
+* [`349ed67`](https://github.com/eslint/eslint/commit/349ed6700e1155384597e1e6035550a96cb8a42d) Update: improve report location for no-mixed-operators (#12328) (Chiawen Chen)
+* [`a102eaa`](https://github.com/eslint/eslint/commit/a102eaa9ac19e1c6d92f79a4033e9048cfb64c0d) Fix: prefer-numeric-literals invalid autofix with adjacent tokens (#12387) (Milos Djermanovic)
+* [`6e7c18d`](https://github.com/eslint/eslint/commit/6e7c18ddb30b32ee5b2e842cc8258aa7aebb7445) Update: enforceForNewInMemberExpressions no-extra-parens (fixes #12428) (#12436) (Milos Djermanovic)
+* [`51fbbd7`](https://github.com/eslint/eslint/commit/51fbbd78f98f223d17071650f5117d07f60dadc2) Fix: array-bracket-newline consistent error with comments (fixes #12416) (#12441) (Milos Djermanovic)
+* [`e657d4c`](https://github.com/eslint/eslint/commit/e657d4ccb9f3dd5cacceaaa40ffe24ac29a1349a) Fix: report full dot location in dot-location (#12452) (Milos Djermanovic)
+* [`2d6e345`](https://github.com/eslint/eslint/commit/2d6e345e3c2626b0f2252f22cfaffdf53ea0871a) Update: make isSpaceBetweenTokens() ignore newline in comments (#12407) (YeonJuan)
+* [`84f71de`](https://github.com/eslint/eslint/commit/84f71de0e686e0fe37b83d6728ce1825caaa44fb) Update: remove default overrides in keyword-spacing (fixes #12369) (#12411) (YeonJuan)
+* [`18a0b0e`](https://github.com/eslint/eslint/commit/18a0b0e3df927428a22b5b5295f9faee4bd57246) Update: improve report location for no-space-in-parens (#12364) (Chiawen Chen)
+* [`d61c8a5`](https://github.com/eslint/eslint/commit/d61c8a5a75447a36276f2d4f84afb3e1129618da) Update: improve report location for no-multi-spaces (#12329) (Chiawen Chen)
+* [`561093f`](https://github.com/eslint/eslint/commit/561093fc4267a4ae317d63bc9f103020fad88802) Upgrade: bump inquirer to ^7.0.0 (#12440) (Joe Graham)
+* [`fb633b2`](https://github.com/eslint/eslint/commit/fb633b2bbd0a390b247047524fdd1f612dbab803) Chore: Add a script for testing with more control (#12444) (Eric Wang)
+* [`012ec51`](https://github.com/eslint/eslint/commit/012ec5151113a2be06fc0e4cd208d714e52dbc57) Sponsors: Sync README with website (ESLint Jenkins)
+* [`874fe16`](https://github.com/eslint/eslint/commit/874fe1642a10a0fb937ccccdd4d22343b84f80dc) New: pass cwd from cli engine (#12389) (Eric Wang)
+* [`b962775`](https://github.com/eslint/eslint/commit/b962775b8cb7c90985a5ab63e56744bb2ba79644) Update: no-self-assign should detect member expression with this (#12279) (Tibor Blenessy)
+* [`02977f2`](https://github.com/eslint/eslint/commit/02977f25a922dd0b8617c16116bb4364d0f30e94) Docs: Clarify `eslint:recommended` semver policy (#12429) (Kevin Partington)
+* [`97045ae`](https://github.com/eslint/eslint/commit/97045ae0805e6503887eef0b131dcb9e70b6d185) Docs: Fixes object type for `rules` in "Use a Plugin" (#12409) (Daisy Develops)
+* [`24ca088`](https://github.com/eslint/eslint/commit/24ca088fdc901feef8f10b050414fbde64b55c7d) Docs: Fix typo in v6 migration guide (#12412) (Benjamim Sonntag)
+* [`b094008`](https://github.com/eslint/eslint/commit/b094008fb196dc1de5b4c27b7dbf0bcbb4b7b352) Chore: update version parameter name (#12402) (Toru Nagashima)
+* [`e5637ba`](https://github.com/eslint/eslint/commit/e5637badd42f087d115f81575b832097fe6fe554) Chore: enable jsdoc/require-description (#12365) (Kai Cataldo)
+* [`d31f337`](https://github.com/eslint/eslint/commit/d31f3370396ec4868722bdc044aa697b135ac183) Sponsors: Sync README with website (ESLint Jenkins)
+* [`7ffb22f`](https://github.com/eslint/eslint/commit/7ffb22f61cf1622511a7fe42b5ead7c3b216df5e) Chore: Clean up inline directive parsing (#12375) (Jordan Eldredge)
+* [`84467c0`](https://github.com/eslint/eslint/commit/84467c07461cc47ee43807ba9014e13700473c5c) Docs: fix wrong max-depth example (fixes #11991) (#12358) (Gabriel R Sezefredo)
+* [`3642342`](https://github.com/eslint/eslint/commit/364234262efabd91fa8bd53161d9d3e1e37e7944) Docs: Fix minor formatting/grammar errors (#12371) (cherryblossom000)
+* [`c47fa0d`](https://github.com/eslint/eslint/commit/c47fa0dfc76211b3b0e5649c63acdd9606ce0eca) Docs: Fix missing word in sentence (#12361) (Dan Boulet)
+* [`8108f49`](https://github.com/eslint/eslint/commit/8108f49f9fa0c2de80b3b66c847551beff585951) Chore: enable additional eslint-plugin-jsdoc rules (#12336) (Kai Cataldo)
+* [`b718d2e`](https://github.com/eslint/eslint/commit/b718d2e6c9fe3fc56aa7cfc68b1a40b5cd8a7c01) Chore: update issue template with --eslint-fix flag (#12352) (James George)
+* [`20ba14d`](https://github.com/eslint/eslint/commit/20ba14dc78fc2654b2920d14877dde21c6c10da4) Sponsors: Sync README with website (ESLint Jenkins)
+* [`566a947`](https://github.com/eslint/eslint/commit/566a947f67c8038a50e204d68723519778a78a0f) Sponsors: Sync README with website (ESLint Jenkins)
+* [`070cbd0`](https://github.com/eslint/eslint/commit/070cbd0a2ec07831962a25c4276d08e097302416) Sponsors: Sync README with website (ESLint Jenkins)
+
 v6.5.1 - September 30, 2019
 
 * [`0d3d7d9`](https://github.com/eslint/eslint/commit/0d3d7d9cdd83a7f0e035c95f716a91b9ecc4868b) Docs: fix typo in no-magic-numbers (#12345) (Josiah Rooney)
diff --git a/README.md b/README.md
index dd414f1d1..ed343a0fd 100644
--- a/README.md
+++ b/README.md
@@ -40,7 +40,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
 
 ## <a name="installation-and-usage"></a>Installation and Usage
 
-Prerequisites: [Node.js](https://nodejs.org/) (`^8.10.0`, `^10.13.0`, or `>=11.10.1`), npm version 3+.
+Prerequisites: [Node.js](https://nodejs.org/) (`^8.10.0`, `^10.13.0`, or `>=11.10.1`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
 
 You can install ESLint using npm:
 
@@ -223,6 +223,11 @@ Teddy Katz
 The people who review and implement new features.
 
 <table><tbody><tr><td align="center" valign="top" width="11%">
+<a href="https://github.com/kaicataldo">
+<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
+Kai Cataldo
+</a>
+</td><td align="center" valign="top" width="11%">
 <a href="https://github.com/aladdin-add">
 <img src="https://github.com/aladdin-add.png?s=75" width="75" height="75"><br />
 薛定谔的猫
@@ -237,11 +242,6 @@ The people who review and implement new features.
 The people who review and fix bugs and help triage issues.
 
 <table><tbody><tr><td align="center" valign="top" width="11%">
-<a href="https://github.com/kaicataldo">
-<img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
-Kai Cataldo
-</a>
-</td><td align="center" valign="top" width="11%">
 <a href="https://github.com/g-plane">
 <img src="https://github.com/g-plane.png?s=75" width="75" height="75"><br />
 Pig Fang
@@ -265,7 +265,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://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" 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://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://www.minitool.com"><img src="https://images.opencollective.com/minitool-software-ltd/6d68e16/logo.png" alt="MiniTool Software Ltd" 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/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://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" 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.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://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://www.crosswordsolver.com"><img src="https://images.opencollective.com/crosswordsolver/d4481d6/logo.png" alt="Crosswordsolver" 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/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/docs/rules/no-inline-comments.md b/docs/rules/no-inline-comments.md
index cf6b7b010..cde77e9e4 100644
--- a/docs/rules/no-inline-comments.md
+++ b/docs/rules/no-inline-comments.md
@@ -35,3 +35,55 @@ var foo = 5;
 var bar = 5;
 //This is a comment below a line of code
 ```
+
+### JSX exception
+
+Comments inside the curly braces in JSX are allowed to be on the same line as the braces, but only if they are not on the same line with other code, and the braces do not enclose an actual expression.
+
+Examples of **incorrect** code for this rule:
+
+```js
+/*eslint no-inline-comments: "error"*/
+
+var foo = <div>{ /* On the same line with other code */ }<h1>Some heading</h1></div>;
+
+var bar = (
+    <div>
+    {   // These braces are not just for the comment, so it can't be on the same line
+        baz
+    }
+    </div>
+);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+/*eslint no-inline-comments: "error"*/
+
+var foo = (
+    <div>
+      {/* These braces are just for this comment and there is nothing else on this line */}
+      <h1>Some heading</h1>
+    </div>
+)
+
+var bar = (
+    <div>
+    {
+        // There is nothing else on this line
+        baz
+    }
+    </div>
+);
+
+var quux = (
+    <div>
+      {/*
+        Multiline
+        comment
+      */}
+      <h1>Some heading</h1>
+    </div>
+)
+```
diff --git a/docs/rules/no-invalid-this.md b/docs/rules/no-invalid-this.md
index b6733eded..7614b59a8 100644
--- a/docs/rules/no-invalid-this.md
+++ b/docs/rules/no-invalid-this.md
@@ -197,6 +197,55 @@ function foo() {
 }
 ```
 
+## Options
+
+This rule has an object option, with one option:
+
+* `"capIsConstructor": false` (default `true`) disables the assumption that a function which name starts with an uppercase is a constructor.
+
+### capIsConstructor
+
+By default, this rule always allows the use of `this` in functions which name starts with an uppercase and anonymous functions that are assigned to a variable which name starts with an uppercase, assuming that those functions are used as constructor functions.
+
+Set `"capIsConstructor"` to `false` if you want those functions to be treated as 'regular' functions.
+
+Examples of **incorrect** code for this rule with `"capIsConstructor"` option set to `false`:
+
+```js
+/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/
+
+"use strict";
+
+function Foo() {
+    this.a = 0;
+}
+
+var bar = function Foo() {
+    this.a = 0;
+}
+
+var Bar = function() {
+    this.a = 0;
+};
+
+Baz = function() {
+    this.a = 0;
+};
+```
+
+Examples of **correct** code for this rule with `"capIsConstructor"` option set to `false`:
+
+```js
+/*eslint no-invalid-this: ["error", { "capIsConstructor": false }]*/
+
+"use strict";
+
+obj.Foo = function Foo() {
+    // OK, this is in a method.
+    this.a = 0;
+};
+```
+
 ## When Not To Use It
 
 If you don't want to be notified about usage of `this` keyword outside of classes or class-like objects, you can safely disable this rule.
diff --git a/docs/rules/no-param-reassign.md b/docs/rules/no-param-reassign.md
index f88d211e2..2ee312c2b 100644
--- a/docs/rules/no-param-reassign.md
+++ b/docs/rules/no-param-reassign.md
@@ -42,7 +42,7 @@ function foo(bar) {
 
 ## Options
 
-This rule takes one option, an object, with a boolean property `"props"` and an array `"ignorePropertyModificationsFor"`. `"props"` is `false` by default. If `"props"` is set to `true`, this rule warns against the modification of parameter properties unless they're included in `"ignorePropertyModificationsFor"`, which is an empty array by default.
+This rule takes one option, an object, with a boolean property `"props"`, and  arrays `"ignorePropertyModificationsFor"` and `"ignorePropertyModificationsForRegex"`. `"props"` is `false` by default. If `"props"` is set to `true`, this rule warns against the modification of parameter properties unless they're included in `"ignorePropertyModificationsFor"` or `"ignorePropertyModificationsForRegex"`, which is an empty array by default.
 
 ### props
 
@@ -124,6 +124,24 @@ function foo(bar) {
 }
 ```
 
+Examples of **correct** code for the `{ "props": true }` option with `"ignorePropertyModificationsForRegex"` set:
+
+```js
+/*eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsForRegex": ["^bar"] }]*/
+
+function foo(bar) {
+    barVar.prop = "value";
+}
+
+function foo(bar) {
+    delete barrito.aaa;
+}
+
+function foo(bar) {
+    bar_.aaa++;
+}
+```
+
 
 ## When Not To Use It
 
diff --git a/docs/rules/no-underscore-dangle.md b/docs/rules/no-underscore-dangle.md
index e112c7a1b..ebe7fd7b6 100644
--- a/docs/rules/no-underscore-dangle.md
+++ b/docs/rules/no-underscore-dangle.md
@@ -42,6 +42,7 @@ This rule has an object option:
 * `"allow"` allows specified identifiers to have dangling underscores
 * `"allowAfterThis": false` (default) disallows dangling underscores in members of the `this` object
 * `"allowAfterSuper": false` (default) disallows dangling underscores in members of the `super` object
+* `"allowAfterThisConstructor": false` (default) disallows dangling underscores in members of the `this.constructor` object
 * `"enforceInMethodNames": false` (default) allows dangling underscores in method names
 
 ### allow
@@ -77,6 +78,17 @@ var a = super.foo_;
 super._bar();
 ```
 
+### allowAfterThisConstructor
+
+Examples of **correct** code for this rule with the `{ "allowAfterThisConstructor": true }` option:
+
+```js
+/*eslint no-underscore-dangle: ["error", { "allowAfterThisConstructor": true }]*/
+
+var a = this.constructor.foo_;
+this.constructor._bar();
+```
+
 ### enforceInMethodNames
 
 Examples of **incorrect** code for this rule with the `{ "enforceInMethodNames": true }` option:
diff --git a/docs/rules/no-unneeded-ternary.md b/docs/rules/no-unneeded-ternary.md
index b4caddf58..e5d4e8011 100644
--- a/docs/rules/no-unneeded-ternary.md
+++ b/docs/rules/no-unneeded-ternary.md
@@ -41,8 +41,6 @@ Examples of **incorrect** code for this rule:
 var a = x === 2 ? true : false;
 
 var a = x ? true : false;
-
-var a = f(x ? x : 1);
 ```
 
 Examples of **correct** code for this rule:
@@ -58,7 +56,7 @@ var a = x ? "Yes" : "No";
 
 var a = x ? y : x;
 
-var a = x ? x : 1;  // Note that this is only allowed as it on the right hand side of an assignment; this type of ternary is disallowed everywhere else. See defaultAssignment option below for more details.
+f(x ? x : 1); // default assignment - would be disallowed if defaultAssignment option set to false. See option details below.
 ```
 
 ## Options
@@ -70,7 +68,7 @@ This rule has an object option:
 
 ### defaultAssignment
 
-The defaultAssignment option allows expressions of the form `x ? x : expr` (where `x` is any identifier and `expr` is any expression) as the right hand side of assignments (but nowhere else).
+When set to `true`, which it is by default, The defaultAssignment option allows expressions of the form `x ? x : expr` (where `x` is any identifier and `expr` is any expression).
 
 Examples of additional **incorrect** code for this rule with the `{ "defaultAssignment": false }` option:
 
@@ -78,8 +76,12 @@ Examples of additional **incorrect** code for this rule with the `{ "defaultAssi
 /*eslint no-unneeded-ternary: ["error", { "defaultAssignment": false }]*/
 
 var a = x ? x : 1;
+
+f(x ? x : 1);
 ```
 
+Note that `defaultAssignment: false` still allows expressions of the form `x ? expr : x` (where the identifier is on the right hand side of the ternary).
+
 ## When Not To Use It
 
 You can turn this rule off if you are not concerned with unnecessary complexity in conditional expressions.
diff --git a/docs/rules/no-unsafe-negation.md b/docs/rules/no-unsafe-negation.md
index 880e9f644..38bb9b02f 100644
--- a/docs/rules/no-unsafe-negation.md
+++ b/docs/rules/no-unsafe-negation.md
@@ -4,12 +4,10 @@ Just as developers might type `-a + b` when they mean `-(a + b)` for the negativ
 
 ## Rule Details
 
-This rule disallows negating the left operand of [Relational Operators](https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Expressions_and_Operators#Relational_operators).
+This rule disallows negating the left operand of the following relational operators:
 
-Relational Operators are:
-
-- `in` operator.
-- `instanceof` operator.
+- [`in` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in).
+- [`instanceof` operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof).
 
 Examples of **incorrect** code for this rule:
 
@@ -72,6 +70,38 @@ if (!(foo) in object) {
 }
 ```
 
+## Options
+
+This rule has an object option:
+
+- `"enforceForOrderingRelations": false` (default) allows negation of the left-hand side of ordering relational operators (`<`, `>`, `<=`, `>=`)
+- `"enforceForOrderingRelations": true` disallows negation of the left-hand side of ordering relational operators
+
+### enforceForOrderingRelations
+
+With this option set to `true` the rule is additionally enforced for:
+
+- `<` operator.
+- `>` operator.
+- `<=` operator.
+- `>=` operator.
+
+The purpose is to avoid expressions such as `! a < b` (which is equivalent to `(a ? 0 : 1) < b`) when what is really intended is `!(a < b)`.
+
+Examples of additional **incorrect** code for this rule with the `{ "enforceForOrderingRelations": true }` option:
+
+```js
+/*eslint no-unsafe-negation: ["error", { "enforceForOrderingRelations": true }]*/
+
+if (! a < b) {}
+
+while (! a > b) {}
+
+foo = ! a <= b;
+
+foo = ! a >= b;
+```
+
 ## When Not To Use It
 
 If you don't want to notify unsafe logical negations, then it's safe to disable this rule.
diff --git a/docs/rules/prefer-exponentiation-operator.md b/docs/rules/prefer-exponentiation-operator.md
new file mode 100644
index 000000000..f5f9e47db
--- /dev/null
+++ b/docs/rules/prefer-exponentiation-operator.md
@@ -0,0 +1,46 @@
+# Disallow the use of `Math.pow` in favor of the `**` operator (prefer-exponentiation-operator)
+
+Introduced in ES2016, the infix exponentiation operator `**` is an alternative for the standard `Math.pow` function.
+
+Infix notation is considered to be more readable and thus more preferable than the function notation.
+
+## Rule Details
+
+This rule disallows calls to `Math.pow` and suggests using the `**` operator instead.
+
+Examples of **incorrect** code for this rule:
+
+```js
+/*eslint prefer-exponentiation-operator: "error"*/
+
+const foo = Math.pow(2, 8);
+
+const bar = Math.pow(a, b);
+
+let baz = Math.pow(a + b, c + d);
+
+let quux = Math.pow(-1, n);
+```
+
+Examples of **correct** code for this rule:
+
+```js
+/*eslint prefer-exponentiation-operator: "error"*/
+
+const foo = 2 ** 8;
+
+const bar = a ** b;
+
+let baz = (a + b) ** (c + d);
+
+let quux = (-1) ** n;
+```
+
+## When Not To Use It
+
+This rule should not be used unless ES2016 is supported in your codebase.
+
+## Further Reading
+
+* [MDN Arithmetic Operators - Exponentiation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation)
+* [Issue 5848: Exponentiation operator ** has different results for numbers and variables from 50 upwards](https://bugs.chromium.org/p/v8/issues/detail?id=5848)
diff --git a/docs/rules/use-isnan.md b/docs/rules/use-isnan.md
index 426eaca5e..0d75251e4 100644
--- a/docs/rules/use-isnan.md
+++ b/docs/rules/use-isnan.md
@@ -43,10 +43,10 @@ if (!isNaN(foo)) {
 
 ## Options
 
-This rule has an object option, with one option:
+This rule has an object option, with two options:
 
-* `"enforceForSwitchCase"` when set to `true` disallows `case NaN` and `switch(NaN)` in `switch` statements. Default is `false`, meaning
-that this rule by default does not warn about `case NaN` or `switch(NaN)`.
+* `"enforceForSwitchCase"` when set to `true` disallows `case NaN` and `switch(NaN)` in `switch` statements. Default is `false`, meaning that this rule by default does not warn about `case NaN` or `switch(NaN)`.
+* `"enforceForIndexOf"` when set to `true` disallows the use of `indexOf` and `lastIndexOf` methods with `NaN`. Default is `false`, meaning that this rule by default does not warn about `indexOf(NaN)` or `lastIndexOf(NaN)` method calls.
 
 ### enforceForSwitchCase
 
@@ -103,3 +103,75 @@ if (Number.isNaN(a)) {
     baz();
 } // ...
 ```
+
+### enforceForIndexOf
+
+The following methods internally use the `===` comparison to match the given value with an array element:
+
+* [`Array.prototype.indexOf`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.indexof)
+* [`Array.prototype.lastIndexOf`](https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.lastindexof)
+
+Therefore, for any array `foo`, `foo.indexOf(NaN)` and `foo.lastIndexOf(NaN)` will always return `-1`.
+
+Set `"enforceForIndexOf"` to `true` if you want this rule to report `indexOf(NaN)` and `lastIndexOf(NaN)` method calls.
+
+Examples of **incorrect** code for this rule with `"enforceForIndexOf"` option set to `true`:
+
+```js
+/*eslint use-isnan: ["error", {"enforceForIndexOf": true}]*/
+
+var hasNaN = myArray.indexOf(NaN) >= 0;
+
+var firstIndex = myArray.indexOf(NaN);
+
+var lastIndex = myArray.lastIndexOf(NaN);
+```
+
+Examples of **correct** code for this rule with `"enforceForIndexOf"` option set to `true`:
+
+```js
+/*eslint use-isnan: ["error", {"enforceForIndexOf": true}]*/
+
+function myIsNaN(val) {
+    return typeof val === "number" && isNaN(val);
+}
+
+function indexOfNaN(arr) {
+    for (var i = 0; i < arr.length; i++) {
+        if (myIsNaN(arr[i])) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+function lastIndexOfNaN(arr) {
+    for (var i = arr.length - 1; i >= 0; i--) {
+        if (myIsNaN(arr[i])) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+var hasNaN = myArray.some(myIsNaN);
+
+var hasNaN = indexOfNaN(myArray) >= 0;
+
+var firstIndex = indexOfNaN(myArray);
+
+var lastIndex = lastIndexOfNaN(myArray);
+
+// ES2015
+var hasNaN = myArray.some(Number.isNaN);
+
+// ES2015
+var firstIndex = myArray.findIndex(Number.isNaN);
+
+// ES2016
+var hasNaN = myArray.includes(NaN);
+```
+
+#### Known Limitations
+
+This option checks methods with the given names, *even if* the object which has the method is *not* an array.
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 1bebf7d69..b457ea940 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -13,7 +13,7 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
 
 ## Installation and Usage
 
-Prerequisites: [Node.js](https://nodejs.org/en/) (>=8.10), npm version 3+.
+Prerequisites: [Node.js](https://nodejs.org/en/) (`^8.10.0`, `^10.13.0`, or `>=11.10.1`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
 
 You can install ESLint using npm:
 
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index 17ed8d9f0..8afd26270 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -667,11 +667,14 @@ class CLIEngine {
     addPlugin(name, pluginObject) {
         const {
             additionalPluginPool,
-            configArrayFactory
+            configArrayFactory,
+            lastConfigArrays
         } = internalSlotsMap.get(this);
 
         additionalPluginPool.set(name, pluginObject);
         configArrayFactory.clearCache();
+        lastConfigArrays.length = 1;
+        lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile();
     }
 
     /**
diff --git a/lib/cli-engine/config-array-factory.js b/lib/cli-engine/config-array-factory.js
index 6e1ba1e02..cf529b6ee 100644
--- a/lib/cli-engine/config-array-factory.js
+++ b/lib/cli-engine/config-array-factory.js
@@ -859,8 +859,14 @@ class ConfigArrayFactory {
         if (filePath) {
             try {
                 writeDebugLogForLoading(request, relativeTo, filePath);
+
+                const startTime = Date.now();
+                const pluginDefinition = require(filePath);
+
+                debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
+
                 return new ConfigDependency({
-                    definition: normalizePlugin(require(filePath)),
+                    definition: normalizePlugin(pluginDefinition),
                     filePath,
                     id,
                     importerName,
diff --git a/lib/linter/linter.js b/lib/linter/linter.js
index 8bd29b947..6d88cb5aa 100644
--- a/lib/linter/linter.js
+++ b/lib/linter/linter.js
@@ -666,6 +666,8 @@ function parse(text, parser, providedParserOptions, filePath) {
         // If the message includes a leading line number, strip it:
         const message = `Parsing error: ${ex.message.replace(/^line \d+:/iu, "").trim()}`;
 
+        debug("%s\n%s", message, ex.stack);
+
         return {
             success: false,
             error: {
diff --git a/lib/rules/comma-dangle.js b/lib/rules/comma-dangle.js
index 0c177296e..fb2d167c7 100644
--- a/lib/rules/comma-dangle.js
+++ b/lib/rules/comma-dangle.js
@@ -41,18 +41,17 @@ function isTrailingCommaAllowed(lastItem) {
 /**
  * Normalize option value.
  * @param {string|Object|undefined} optionValue The 1st option value to normalize.
+ * @param {number} ecmaVersion The normalized ECMAScript version.
  * @returns {Object} The normalized option value.
  */
-function normalizeOptions(optionValue) {
+function normalizeOptions(optionValue, ecmaVersion) {
     if (typeof optionValue === "string") {
         return {
             arrays: optionValue,
             objects: optionValue,
             imports: optionValue,
             exports: optionValue,
-
-            // For backward compatibility, always ignore functions.
-            functions: "ignore"
+            functions: (!ecmaVersion || ecmaVersion < 8) ? "ignore" : optionValue
         };
     }
     if (typeof optionValue === "object" && optionValue !== null) {
@@ -135,7 +134,8 @@ module.exports = {
     },
 
     create(context) {
-        const options = normalizeOptions(context.options[0]);
+        const options = normalizeOptions(context.options[0], context.parserOptions.ecmaVersion);
+
         const sourceCode = context.getSourceCode();
 
         /**
diff --git a/lib/rules/dot-location.js b/lib/rules/dot-location.js
index 812988efa..d483e217a 100644
--- a/lib/rules/dot-location.js
+++ b/lib/rules/dot-location.js
@@ -47,19 +47,18 @@ module.exports = {
 
         /**
          * Reports if the dot between object and property is on the correct loccation.
-         * @param {ASTNode} obj The object owning the property.
-         * @param {ASTNode} prop The property of the object.
-         * @param {ASTNode} node The corresponding node of the token.
+         * @param {ASTNode} node The `MemberExpression` node.
          * @returns {void}
          */
-        function checkDotLocation(obj, prop, node) {
-            const dot = sourceCode.getTokenBefore(prop);
+        function checkDotLocation(node) {
+            const property = node.property;
+            const dot = sourceCode.getTokenBefore(property);
 
             // `obj` expression can be parenthesized, but those paren tokens are not a part of the `obj` node.
             const tokenBeforeDot = sourceCode.getTokenBefore(dot);
 
             const textBeforeDot = sourceCode.getText().slice(tokenBeforeDot.range[1], dot.range[0]);
-            const textAfterDot = sourceCode.getText().slice(dot.range[1], prop.range[0]);
+            const textAfterDot = sourceCode.getText().slice(dot.range[1], property.range[0]);
 
             if (onObject) {
                 if (!astUtils.isTokenOnSameLine(tokenBeforeDot, dot)) {
@@ -69,15 +68,15 @@ module.exports = {
                         node,
                         loc: dot.loc,
                         messageId: "expectedDotAfterObject",
-                        fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${neededTextAfterToken}.${textBeforeDot}${textAfterDot}`)
+                        fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], property.range[0]], `${neededTextAfterToken}.${textBeforeDot}${textAfterDot}`)
                     });
                 }
-            } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
+            } else if (!astUtils.isTokenOnSameLine(dot, property)) {
                 context.report({
                     node,
                     loc: dot.loc,
                     messageId: "expectedDotBeforeProperty",
-                    fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
+                    fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], property.range[0]], `${textBeforeDot}${textAfterDot}.`)
                 });
             }
         }
@@ -89,7 +88,7 @@ module.exports = {
          */
         function checkNode(node) {
             if (!node.computed) {
-                checkDotLocation(node.object, node.property, node);
+                checkDotLocation(node);
             }
         }
 
diff --git a/lib/rules/function-call-argument-newline.js b/lib/rules/function-call-argument-newline.js
index 8bf31f7c7..31ebc097c 100644
--- a/lib/rules/function-call-argument-newline.js
+++ b/lib/rules/function-call-argument-newline.js
@@ -40,13 +40,13 @@ module.exports = {
         const checkers = {
             unexpected: {
                 messageId: "unexpectedLineBreak",
-                check: (prevToken, currentToken) => prevToken.loc.start.line !== currentToken.loc.start.line,
+                check: (prevToken, currentToken) => prevToken.loc.end.line !== currentToken.loc.start.line,
                 createFix: (token, tokenBefore) => fixer =>
                     fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ")
             },
             missing: {
                 messageId: "missingLineBreak",
-                check: (prevToken, currentToken) => prevToken.loc.start.line === currentToken.loc.start.line,
+                check: (prevToken, currentToken) => prevToken.loc.end.line === currentToken.loc.start.line,
                 createFix: (token, tokenBefore) => fixer =>
                     fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n")
             }
@@ -61,7 +61,7 @@ module.exports = {
          */
         function checkArguments(node, checker) {
             for (let i = 1; i < node.arguments.length; i++) {
-                const prevArgToken = sourceCode.getFirstToken(node.arguments[i - 1]);
+                const prevArgToken = sourceCode.getLastToken(node.arguments[i - 1]);
                 const currentArgToken = sourceCode.getFirstToken(node.arguments[i]);
 
                 if (checker.check(prevArgToken, currentArgToken)) {
@@ -101,10 +101,10 @@ module.exports = {
             } else if (option === "always") {
                 checkArguments(node, checkers.missing);
             } else if (option === "consistent") {
-                const firstArgToken = sourceCode.getFirstToken(node.arguments[0]);
+                const firstArgToken = sourceCode.getLastToken(node.arguments[0]);
                 const secondArgToken = sourceCode.getFirstToken(node.arguments[1]);
 
-                if (firstArgToken.loc.start.line === secondArgToken.loc.start.line) {
+                if (firstArgToken.loc.end.line === secondArgToken.loc.start.line) {
                     checkArguments(node, checkers.unexpected);
                 } else {
                     checkArguments(node, checkers.missing);
diff --git a/lib/rules/index.js b/lib/rules/index.js
index 8b0abc4ee..dbda93fb3 100644
--- a/lib/rules/index.js
+++ b/lib/rules/index.js
@@ -238,6 +238,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
     "prefer-arrow-callback": () => require("./prefer-arrow-callback"),
     "prefer-const": () => require("./prefer-const"),
     "prefer-destructuring": () => require("./prefer-destructuring"),
+    "prefer-exponentiation-operator": () => require("./prefer-exponentiation-operator"),
     "prefer-named-capture-group": () => require("./prefer-named-capture-group"),
     "prefer-numeric-literals": () => require("./prefer-numeric-literals"),
     "prefer-object-spread": () => require("./prefer-object-spread"),
diff --git a/lib/rules/no-cond-assign.js b/lib/rules/no-cond-assign.js
index 67dcd28b2..b1d40f9c8 100644
--- a/lib/rules/no-cond-assign.js
+++ b/lib/rules/no-cond-assign.js
@@ -2,10 +2,21 @@
  * @fileoverview Rule to flag assignment in a conditional statement's test expression
  * @author Stephen Murray <spmurrayzzz>
  */
+
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
 const astUtils = require("./utils/ast-utils");
 
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const TEST_CONDITION_PARENT_TYPES = new Set(["IfStatement", "WhileStatement", "DoWhileStatement", "ForStatement", "ConditionalExpression"]);
+
 const NODE_DESCRIPTIONS = {
     DoWhileStatement: "a 'do...while' statement",
     ForStatement: "a 'for' statement",
@@ -55,7 +66,7 @@ module.exports = {
          */
         function isConditionalTestExpression(node) {
             return node.parent &&
-                node.parent.test &&
+                TEST_CONDITION_PARENT_TYPES.has(node.parent.type) &&
                 node === node.parent.test;
         }
 
diff --git a/lib/rules/no-inline-comments.js b/lib/rules/no-inline-comments.js
index b35db1141..bd226ecc3 100644
--- a/lib/rules/no-inline-comments.js
+++ b/lib/rules/no-inline-comments.js
@@ -35,22 +35,36 @@ module.exports = {
          */
         function testCodeAroundComment(node) {
 
-            // Get the whole line and cut it off at the start of the comment
-            const startLine = String(sourceCode.lines[node.loc.start.line - 1]);
-            const endLine = String(sourceCode.lines[node.loc.end.line - 1]);
+            const startLine = String(sourceCode.lines[node.loc.start.line - 1]),
+                endLine = String(sourceCode.lines[node.loc.end.line - 1]),
+                preamble = startLine.slice(0, node.loc.start.column).trim(),
+                postamble = endLine.slice(node.loc.end.column).trim(),
+                isPreambleEmpty = !preamble,
+                isPostambleEmpty = !postamble;
 
-            const preamble = startLine.slice(0, node.loc.start.column).trim();
+            // Nothing on both sides
+            if (isPreambleEmpty && isPostambleEmpty) {
+                return;
+            }
 
-            // Also check after the comment
-            const postamble = endLine.slice(node.loc.end.column).trim();
+            // JSX Exception
+            if (
+                (isPreambleEmpty || preamble === "{") &&
+                (isPostambleEmpty || postamble === "}")
+            ) {
+                const enclosingNode = sourceCode.getNodeByRangeIndex(node.range[0]);
 
-            // Check that this comment isn't an ESLint directive
-            const isDirective = astUtils.isDirectiveComment(node);
+                if (enclosingNode && enclosingNode.type === "JSXEmptyExpression") {
+                    return;
+                }
+            }
 
-            // Should be empty if there was only whitespace around the comment
-            if (!isDirective && (preamble || postamble)) {
-                context.report({ node, message: "Unexpected comment inline with code." });
+            // Don't report ESLint directive comments
+            if (astUtils.isDirectiveComment(node)) {
+                return;
             }
+
+            context.report({ node, message: "Unexpected comment inline with code." });
         }
 
         //--------------------------------------------------------------------------
diff --git a/lib/rules/no-invalid-this.js b/lib/rules/no-invalid-this.js
index b1dddd931..5398fc3b5 100644
--- a/lib/rules/no-invalid-this.js
+++ b/lib/rules/no-invalid-this.js
@@ -26,10 +26,23 @@ module.exports = {
             url: "https://eslint.org/docs/rules/no-invalid-this"
         },
 
-        schema: []
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    capIsConstructor: {
+                        type: "boolean",
+                        default: true
+                    }
+                },
+                additionalProperties: false
+            }
+        ]
     },
 
     create(context) {
+        const options = context.options[0] || {};
+        const capIsConstructor = options.capIsConstructor !== false;
         const stack = [],
             sourceCode = context.getSourceCode();
 
@@ -48,7 +61,8 @@ module.exports = {
                 current.init = true;
                 current.valid = !astUtils.isDefaultThisBinding(
                     current.node,
-                    sourceCode
+                    sourceCode,
+                    { capIsConstructor }
                 );
             }
             return current;
diff --git a/lib/rules/no-misleading-character-class.js b/lib/rules/no-misleading-character-class.js
index 6d8358161..9315ba649 100644
--- a/lib/rules/no-misleading-character-class.js
+++ b/lib/rules/no-misleading-character-class.js
@@ -130,12 +130,6 @@ module.exports = {
          * @returns {void}
          */
         function verify(node, pattern, flags) {
-            const patternNode = parser.parsePattern(
-                pattern,
-                0,
-                pattern.length,
-                flags.includes("u")
-            );
             const has = {
                 surrogatePairWithoutUFlag: false,
                 combiningClass: false,
@@ -144,6 +138,20 @@ module.exports = {
                 regionalIndicatorSymbol: false,
                 zwj: false
             };
+            let patternNode;
+
+            try {
+                patternNode = parser.parsePattern(
+                    pattern,
+                    0,
+                    pattern.length,
+                    flags.includes("u")
+                );
+            } catch (e) {
+
+                // Ignore regular expressions with syntax errors
+                return;
+            }
 
             visitRegExpAST(patternNode, {
                 onCharacterClassEnter(ccNode) {
diff --git a/lib/rules/no-param-reassign.js b/lib/rules/no-param-reassign.js
index edaaef537..d65eb3476 100644
--- a/lib/rules/no-param-reassign.js
+++ b/lib/rules/no-param-reassign.js
@@ -45,6 +45,13 @@ module.exports = {
                                     type: "string"
                                 },
                                 uniqueItems: true
+                            },
+                            ignorePropertyModificationsForRegex: {
+                                type: "array",
+                                items: {
+                                    type: "string"
+                                },
+                                uniqueItems: true
                             }
                         },
                         additionalProperties: false
@@ -57,6 +64,7 @@ module.exports = {
     create(context) {
         const props = context.options[0] && context.options[0].props;
         const ignoredPropertyAssignmentsFor = context.options[0] && context.options[0].ignorePropertyModificationsFor || [];
+        const ignoredPropertyAssignmentsForRegex = context.options[0] && context.options[0].ignorePropertyModificationsForRegex || [];
 
         /**
          * Checks whether or not the reference modifies properties of its variable.
@@ -136,6 +144,19 @@ module.exports = {
             return false;
         }
 
+        /**
+         * Tests that an identifier name matches any of the ignored property assignments.
+         * First we test strings in ignoredPropertyAssignmentsFor.
+         * Then we instantiate and test RegExp objects from ignoredPropertyAssignmentsForRegex strings.
+         * @param {string} identifierName A string that describes the name of an identifier to
+         * ignore property assignments for.
+         * @returns {boolean} Whether the string matches an ignored property assignment regular expression or not.
+         */
+        function isIgnoredPropertyAssignment(identifierName) {
+            return ignoredPropertyAssignmentsFor.includes(identifierName) ||
+                ignoredPropertyAssignmentsForRegex.some(ignored => new RegExp(ignored, "u").test(identifierName));
+        }
+
         /**
          * Reports a reference if is non initializer and writable.
          * @param {Reference} reference A reference to check.
@@ -157,7 +178,7 @@ module.exports = {
             ) {
                 if (reference.isWrite()) {
                     context.report({ node: identifier, message: "Assignment to function parameter '{{name}}'.", data: { name: identifier.name } });
-                } else if (props && isModifyingProp(reference) && ignoredPropertyAssignmentsFor.indexOf(identifier.name) === -1) {
+                } else if (props && isModifyingProp(reference) && !isIgnoredPropertyAssignment(identifier.name)) {
                     context.report({ node: identifier, message: "Assignment to property of function parameter '{{name}}'.", data: { name: identifier.name } });
                 }
             }
diff --git a/lib/rules/no-tabs.js b/lib/rules/no-tabs.js
index 0c0a22011..3fc0b78b6 100644
--- a/lib/rules/no-tabs.js
+++ b/lib/rules/no-tabs.js
@@ -55,8 +55,14 @@ module.exports = {
                         context.report({
                             node,
                             loc: {
-                                line: index + 1,
-                                column: match.index
+                                start: {
+                                    line: index + 1,
+                                    column: match.index
+                                },
+                                end: {
+                                    line: index + 1,
+                                    column: match.index + match[0].length
+                                }
                             },
                             message: "Unexpected tab character."
                         });
diff --git a/lib/rules/no-trailing-spaces.js b/lib/rules/no-trailing-spaces.js
index 83c01d5e7..3a4124f4c 100644
--- a/lib/rules/no-trailing-spaces.js
+++ b/lib/rules/no-trailing-spaces.js
@@ -90,7 +90,11 @@ module.exports = {
             const lines = new Set();
 
             comments.forEach(comment => {
-                for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) {
+                const endLine = comment.type === "Block"
+                    ? comment.loc.end.line - 1
+                    : comment.loc.end.line;
+
+                for (let i = comment.loc.start.line; i <= endLine; i++) {
                     lines.add(i);
                 }
             });
@@ -122,7 +126,7 @@ module.exports = {
                     fixRange = [];
 
                 for (let i = 0, ii = lines.length; i < ii; i++) {
-                    const matches = re.exec(lines[i]);
+                    const lineNumber = i + 1;
 
                     /*
                      * Always add linebreak length to line length to accommodate for line break (\n or \r\n)
@@ -132,14 +136,22 @@ module.exports = {
                     const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
                     const lineLength = lines[i].length + linebreakLength;
 
+                    const matches = re.exec(lines[i]);
+
                     if (matches) {
                         const location = {
-                            line: i + 1,
-                            column: matches.index
+                            start: {
+                                line: lineNumber,
+                                column: matches.index
+                            },
+                            end: {
+                                line: lineNumber,
+                                column: lineLength - linebreakLength
+                            }
                         };
 
-                        const rangeStart = totalLength + location.column;
-                        const rangeEnd = totalLength + lineLength - linebreakLength;
+                        const rangeStart = totalLength + location.start.column;
+                        const rangeEnd = totalLength + location.end.column;
                         const containingNode = sourceCode.getNodeByRangeIndex(rangeStart);
 
                         if (containingNode && containingNode.type === "TemplateElement" &&
@@ -160,7 +172,7 @@ module.exports = {
 
                         fixRange = [rangeStart, rangeEnd];
 
-                        if (!ignoreComments || !commentLineNumbers.has(location.line)) {
+                        if (!ignoreComments || !commentLineNumbers.has(lineNumber)) {
                             report(node, location, fixRange);
                         }
                     }
diff --git a/lib/rules/no-underscore-dangle.js b/lib/rules/no-underscore-dangle.js
index 3f59815b5..e910e2739 100644
--- a/lib/rules/no-underscore-dangle.js
+++ b/lib/rules/no-underscore-dangle.js
@@ -38,6 +38,10 @@ module.exports = {
                         type: "boolean",
                         default: false
                     },
+                    allowAfterThisConstructor: {
+                        type: "boolean",
+                        default: false
+                    },
                     enforceInMethodNames: {
                         type: "boolean",
                         default: false
@@ -54,6 +58,7 @@ module.exports = {
         const ALLOWED_VARIABLES = options.allow ? options.allow : [];
         const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
         const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
+        const allowAfterThisConstructor = typeof options.allowAfterThisConstructor !== "undefined" ? options.allowAfterThisConstructor : false;
         const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
 
         //-------------------------------------------------------------------------
@@ -72,7 +77,7 @@ module.exports = {
 
         /**
          * Check if identifier has a underscore at the end
-         * @param {ASTNode} identifier node to evaluate
+         * @param {string} identifier name of the node
          * @returns {boolean} true if its is present
          * @private
          */
@@ -84,7 +89,7 @@ module.exports = {
 
         /**
          * Check if identifier is a special case member expression
-         * @param {ASTNode} identifier node to evaluate
+         * @param {string} identifier name of the node
          * @returns {boolean} true if its is a special case
          * @private
          */
@@ -94,7 +99,7 @@ module.exports = {
 
         /**
          * Check if identifier is a special case variable expression
-         * @param {ASTNode} identifier node to evaluate
+         * @param {string} identifier name of the node
          * @returns {boolean} true if its is a special case
          * @private
          */
@@ -104,6 +109,18 @@ module.exports = {
             return identifier === "_";
         }
 
+        /**
+         * Check if a node is a member reference of this.constructor
+         * @param {ASTNode} node node to evaluate
+         * @returns {boolean} true if it is a reference on this.constructor
+         * @private
+         */
+        function isThisConstructorReference(node) {
+            return node.object.type === "MemberExpression" &&
+                node.object.property.name === "constructor" &&
+                node.object.object.type === "ThisExpression";
+        }
+
         /**
          * Check if function has a underscore at the end
          * @param {ASTNode} node node to evaluate
@@ -156,11 +173,13 @@ module.exports = {
         function checkForTrailingUnderscoreInMemberExpression(node) {
             const identifier = node.property.name,
                 isMemberOfThis = node.object.type === "ThisExpression",
-                isMemberOfSuper = node.object.type === "Super";
+                isMemberOfSuper = node.object.type === "Super",
+                isMemberOfThisConstructor = isThisConstructorReference(node);
 
             if (typeof identifier !== "undefined" && hasTrailingUnderscore(identifier) &&
                 !(isMemberOfThis && allowAfterThis) &&
                 !(isMemberOfSuper && allowAfterSuper) &&
+                !(isMemberOfThisConstructor && allowAfterThisConstructor) &&
                 !isSpecialCaseIdentifierForMemberExpression(identifier) && !isAllowed(identifier)) {
                 context.report({
                     node,
diff --git a/lib/rules/no-unsafe-negation.js b/lib/rules/no-unsafe-negation.js
index 5226b367d..5c8f569d7 100644
--- a/lib/rules/no-unsafe-negation.js
+++ b/lib/rules/no-unsafe-negation.js
@@ -16,14 +16,23 @@ const astUtils = require("./utils/ast-utils");
 //------------------------------------------------------------------------------
 
 /**
- * Checks whether the given operator is a relational operator or not.
+ * Checks whether the given operator is `in` or `instanceof`
  * @param {string} op The operator type to check.
- * @returns {boolean} `true` if the operator is a relational operator.
+ * @returns {boolean} `true` if the operator is `in` or `instanceof`
  */
-function isRelationalOperator(op) {
+function isInOrInstanceOfOperator(op) {
     return op === "in" || op === "instanceof";
 }
 
+/**
+ * Checks whether the given operator is an ordering relational operator or not.
+ * @param {string} op The operator type to check.
+ * @returns {boolean} `true` if the operator is an ordering relational operator.
+ */
+function isOrderingRelationalOperator(op) {
+    return op === "<" || op === ">" || op === ">=" || op === "<=";
+}
+
 /**
  * Checks whether the given node is a logical negation expression or not.
  * @param {ASTNode} node The node to check.
@@ -48,7 +57,18 @@ module.exports = {
             url: "https://eslint.org/docs/rules/no-unsafe-negation"
         },
 
-        schema: [],
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    enforceForOrderingRelations: {
+                        type: "boolean",
+                        default: false
+                    }
+                },
+                additionalProperties: false
+            }
+        ],
         fixable: null,
         messages: {
             unexpected: "Unexpected negating the left operand of '{{operator}}' operator."
@@ -57,10 +77,15 @@ module.exports = {
 
     create(context) {
         const sourceCode = context.getSourceCode();
+        const options = context.options[0] || {};
+        const enforceForOrderingRelations = options.enforceForOrderingRelations === true;
 
         return {
             BinaryExpression(node) {
-                if (isRelationalOperator(node.operator) &&
+                const orderingRelationRuleApplies = enforceForOrderingRelations && isOrderingRelationalOperator(node.operator);
+
+                if (
+                    (isInOrInstanceOfOperator(node.operator) || orderingRelationRuleApplies) &&
                     isNegation(node.left) &&
                     !astUtils.isParenthesised(sourceCode, node.left)
                 ) {
diff --git a/lib/rules/operator-assignment.js b/lib/rules/operator-assignment.js
index 63982cf39..e294668b4 100644
--- a/lib/rules/operator-assignment.js
+++ b/lib/rules/operator-assignment.js
@@ -150,6 +150,11 @@ module.exports = {
                                 const leftText = sourceCode.getText().slice(node.range[0], equalsToken.range[0]);
                                 const rightText = sourceCode.getText().slice(operatorToken.range[1], node.right.range[1]);
 
+                                // Check for comments that would be removed.
+                                if (sourceCode.commentsExistBetween(equalsToken, operatorToken)) {
+                                    return null;
+                                }
+
                                 return fixer.replaceText(node, `${leftText}${expr.operator}=${rightText}`);
                             }
                             return null;
@@ -182,11 +187,17 @@ module.exports = {
                     messageId: "unexpected",
                     fix(fixer) {
                         if (canBeFixed(node.left)) {
+                            const firstToken = sourceCode.getFirstToken(node);
                             const operatorToken = getOperatorToken(node);
                             const leftText = sourceCode.getText().slice(node.range[0], operatorToken.range[0]);
                             const newOperator = node.operator.slice(0, -1);
                             let rightText;
 
+                            // Check for comments that would be duplicated.
+                            if (sourceCode.commentsExistBetween(firstToken, operatorToken)) {
+                                return null;
+                            }
+
                             // If this change would modify precedence (e.g. `foo *= bar + 1` => `foo = foo * (bar + 1)`), parenthesize the right side.
                             if (
                                 astUtils.getPrecedence(node.right) <= astUtils.getPrecedence({ type: "BinaryExpression", operator: newOperator }) &&
@@ -194,7 +205,17 @@ module.exports = {
                             ) {
                                 rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`;
                             } else {
-                                rightText = sourceCode.text.slice(operatorToken.range[1], node.range[1]);
+                                const firstRightToken = sourceCode.getFirstToken(node.right);
+                                let rightTextPrefix = "";
+
+                                if (
+                                    operatorToken.range[1] === firstRightToken.range[0] &&
+                                    !astUtils.canTokensBeAdjacent(newOperator, firstRightToken)
+                                ) {
+                                    rightTextPrefix = " "; // foo+=+bar -> foo= foo+ +bar
+                                }
+
+                                rightText = `${rightTextPrefix}${sourceCode.text.slice(operatorToken.range[1], node.range[1])}`;
                             }
 
                             return fixer.replaceText(node, `${leftText}= ${leftText}${newOperator}${rightText}`);
diff --git a/lib/rules/prefer-exponentiation-operator.js b/lib/rules/prefer-exponentiation-operator.js
new file mode 100644
index 000000000..5e75ef472
--- /dev/null
+++ b/lib/rules/prefer-exponentiation-operator.js
@@ -0,0 +1,189 @@
+/**
+ * @fileoverview Rule to disallow Math.pow in favor of the ** operator
+ * @author Milos Djermanovic
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+const { CALL, ReferenceTracker } = require("eslint-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const PRECEDENCE_OF_EXPONENTIATION_EXPR = astUtils.getPrecedence({ type: "BinaryExpression", operator: "**" });
+
+/**
+ * Determines whether the given node needs parens if used as the base in an exponentiation binary expression.
+ * @param {ASTNode} base The node to check.
+ * @returns {boolean} `true` if the node needs to be parenthesised.
+ */
+function doesBaseNeedParens(base) {
+    return (
+
+        // '**' is right-associative, parens are needed when Math.pow(a ** b, c) is converted to (a ** b) ** c
+        astUtils.getPrecedence(base) <= PRECEDENCE_OF_EXPONENTIATION_EXPR ||
+
+        // An unary operator cannot be used immediately before an exponentiation expression
+        base.type === "UnaryExpression"
+    );
+}
+
+/**
+ * Determines whether the given node needs parens if used as the exponent in an exponentiation binary expression.
+ * @param {ASTNode} exponent The node to check.
+ * @returns {boolean} `true` if the node needs to be parenthesised.
+ */
+function doesExponentNeedParens(exponent) {
+
+    // '**' is right-associative, there is no need for parens when Math.pow(a, b ** c) is converted to a ** b ** c
+    return astUtils.getPrecedence(exponent) < PRECEDENCE_OF_EXPONENTIATION_EXPR;
+}
+
+/**
+ * Determines whether an exponentiation binary expression at the place of the given node would need parens.
+ * @param {ASTNode} node A node that would be replaced by an exponentiation binary expression.
+ * @param {SourceCode} sourceCode A SourceCode object.
+ * @returns {boolean} `true` if the expression needs to be parenthesised.
+ */
+function doesExponentiationExpressionNeedParens(node, sourceCode) {
+    const parent = node.parent;
+
+    const needsParens = (
+        parent.type === "ClassDeclaration" ||
+        (
+            parent.type.endsWith("Expression") &&
+            astUtils.getPrecedence(parent) >= PRECEDENCE_OF_EXPONENTIATION_EXPR &&
+            !(parent.type === "BinaryExpression" && parent.operator === "**" && parent.right === node) &&
+            !((parent.type === "CallExpression" || parent.type === "NewExpression") && parent.arguments.includes(node)) &&
+            !(parent.type === "MemberExpression" && parent.computed && parent.property === node) &&
+            !(parent.type === "ArrayExpression")
+        )
+    );
+
+    return needsParens && !astUtils.isParenthesised(sourceCode, node);
+}
+
+/**
+ * Optionally parenthesizes given text.
+ * @param {string} text The text to parenthesize.
+ * @param {boolean} shouldParenthesize If `true`, the text will be parenthesised.
+ * @returns {string} parenthesised or unchanged text.
+ */
+function parenthesizeIfShould(text, shouldParenthesize) {
+    return shouldParenthesize ? `(${text})` : text;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "suggestion",
+
+        docs: {
+            description: "disallow the use of `Math.pow` in favor of the `**` operator",
+            category: "Stylistic Issues",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/prefer-exponentiation-operator"
+        },
+
+        schema: [],
+        fixable: "code",
+
+        messages: {
+            useExponentiation: "Use the '**' operator instead of 'Math.pow'."
+        }
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+
+        /**
+         * Reports the given node.
+         * @param {ASTNode} node 'Math.pow()' node to report.
+         * @returns {void}
+         */
+        function report(node) {
+            context.report({
+                node,
+                messageId: "useExponentiation",
+                fix(fixer) {
+                    if (
+                        node.arguments.length !== 2 ||
+                        node.arguments.some(arg => arg.type === "SpreadElement") ||
+                        sourceCode.getCommentsInside(node).length > 0
+                    ) {
+                        return null;
+                    }
+
+                    const base = node.arguments[0],
+                        exponent = node.arguments[1],
+                        baseText = sourceCode.getText(base),
+                        exponentText = sourceCode.getText(exponent),
+                        shouldParenthesizeBase = doesBaseNeedParens(base),
+                        shouldParenthesizeExponent = doesExponentNeedParens(exponent),
+                        shouldParenthesizeAll = doesExponentiationExpressionNeedParens(node, sourceCode);
+
+                    let prefix = "",
+                        suffix = "";
+
+                    if (!shouldParenthesizeAll) {
+                        if (!shouldParenthesizeBase) {
+                            const firstReplacementToken = sourceCode.getFirstToken(base),
+                                tokenBefore = sourceCode.getTokenBefore(node);
+
+                            if (
+                                tokenBefore &&
+                                tokenBefore.range[1] === node.range[0] &&
+                                !astUtils.canTokensBeAdjacent(tokenBefore, firstReplacementToken)
+                            ) {
+                                prefix = " "; // a+Math.pow(++b, c) -> a+ ++b**c
+                            }
+                        }
+                        if (!shouldParenthesizeExponent) {
+                            const lastReplacementToken = sourceCode.getLastToken(exponent),
+                                tokenAfter = sourceCode.getTokenAfter(node);
+
+                            if (
+                                tokenAfter &&
+                                node.range[1] === tokenAfter.range[0] &&
+                                !astUtils.canTokensBeAdjacent(lastReplacementToken, tokenAfter)
+                            ) {
+                                suffix = " "; // Math.pow(a, b)in c -> a**b in c
+                            }
+                        }
+                    }
+
+                    const baseReplacement = parenthesizeIfShould(baseText, shouldParenthesizeBase),
+                        exponentReplacement = parenthesizeIfShould(exponentText, shouldParenthesizeExponent),
+                        replacement = parenthesizeIfShould(`${baseReplacement}**${exponentReplacement}`, shouldParenthesizeAll);
+
+                    return fixer.replaceText(node, `${prefix}${replacement}${suffix}`);
+                }
+            });
+        }
+
+        return {
+            Program() {
+                const scope = context.getScope();
+                const tracker = new ReferenceTracker(scope);
+                const trackMap = {
+                    Math: {
+                        pow: { [CALL]: true }
+                    }
+                };
+
+                for (const { node } of tracker.iterateGlobalReferences(trackMap)) {
+                    report(node);
+                }
+            }
+        };
+    }
+};
diff --git a/lib/rules/space-infix-ops.js b/lib/rules/space-infix-ops.js
index b2fbe47b4..bd2c0ae0e 100644
--- a/lib/rules/space-infix-ops.js
+++ b/lib/rules/space-infix-ops.js
@@ -69,7 +69,7 @@ module.exports = {
         function report(mainNode, culpritToken) {
             context.report({
                 node: mainNode,
-                loc: culpritToken.loc.start,
+                loc: culpritToken.loc,
                 message: "Operator '{{operator}}' must be spaced.",
                 data: {
                     operator: culpritToken.value
diff --git a/lib/rules/use-isnan.js b/lib/rules/use-isnan.js
index b2eb84b7b..cd9ccdbaf 100644
--- a/lib/rules/use-isnan.js
+++ b/lib/rules/use-isnan.js
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
@@ -40,6 +46,10 @@ module.exports = {
                     enforceForSwitchCase: {
                         type: "boolean",
                         default: false
+                    },
+                    enforceForIndexOf: {
+                        type: "boolean",
+                        default: false
                     }
                 },
                 additionalProperties: false
@@ -49,16 +59,18 @@ module.exports = {
         messages: {
             comparisonWithNaN: "Use the isNaN function to compare with NaN.",
             switchNaN: "'switch(NaN)' can never match a case clause. Use Number.isNaN instead of the switch.",
-            caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch."
+            caseNaN: "'case NaN' can never match. Use Number.isNaN before the switch.",
+            indexOfNaN: "Array prototype method '{{ methodName }}' cannot find NaN."
         }
     },
 
     create(context) {
 
         const enforceForSwitchCase = context.options[0] && context.options[0].enforceForSwitchCase;
+        const enforceForIndexOf = context.options[0] && context.options[0].enforceForIndexOf;
 
         /**
-         * Checks the given `BinaryExpression` node.
+         * Checks the given `BinaryExpression` node for `foo === NaN` and other comparisons.
          * @param {ASTNode} node The node to check.
          * @returns {void}
          */
@@ -72,7 +84,7 @@ module.exports = {
         }
 
         /**
-         * Checks the discriminant and all case clauses of the given `SwitchStatement` node.
+         * Checks the discriminant and all case clauses of the given `SwitchStatement` node for `switch(NaN)` and `case NaN:`
          * @param {ASTNode} node The node to check.
          * @returns {void}
          */
@@ -88,6 +100,27 @@ module.exports = {
             }
         }
 
+        /**
+         * Checks the the given `CallExpression` node for `.indexOf(NaN)` and `.lastIndexOf(NaN)`.
+         * @param {ASTNode} node The node to check.
+         * @returns {void}
+         */
+        function checkCallExpression(node) {
+            const callee = node.callee;
+
+            if (callee.type === "MemberExpression") {
+                const methodName = astUtils.getStaticPropertyName(callee);
+
+                if (
+                    (methodName === "indexOf" || methodName === "lastIndexOf") &&
+                    node.arguments.length === 1 &&
+                    isNaNIdentifier(node.arguments[0])
+                ) {
+                    context.report({ node, messageId: "indexOfNaN", data: { methodName } });
+                }
+            }
+        }
+
         const listeners = {
             BinaryExpression: checkBinaryExpression
         };
@@ -96,6 +129,10 @@ module.exports = {
             listeners.SwitchStatement = checkSwitchStatement;
         }
 
+        if (enforceForIndexOf) {
+            listeners.CallExpression = checkCallExpression;
+        }
+
         return listeners;
     }
 };
diff --git a/lib/rules/utils/ast-utils.js b/lib/rules/utils/ast-utils.js
index 17e056c24..ffb8bace8 100644
--- a/lib/rules/utils/ast-utils.js
+++ b/lib/rules/utils/ast-utils.js
@@ -581,23 +581,31 @@ module.exports = {
      *
      * First, this checks the node:
      *
-     * - The function name does not start with uppercase (it's a constructor).
+     * - The function name does not start with uppercase. It's a convention to capitalize the names
+     *   of constructor functions. This check is not performed if `capIsConstructor` is set to `false`.
      * - The function does not have a JSDoc comment that has a @this tag.
      *
      * Next, this checks the location of the node.
      * If the location is below, this judges `this` is valid.
      *
      * - The location is not on an object literal.
-     * - The location is not assigned to a variable which starts with an uppercase letter.
+     * - The location is not assigned to a variable which starts with an uppercase letter. Applies to anonymous
+     *   functions only, as the name of the variable is considered to be the name of the function in this case.
+     *   This check is not performed if `capIsConstructor` is set to `false`.
      * - The location is not on an ES2015 class.
      * - Its `bind`/`call`/`apply` method is not called directly.
      * - The function is not a callback of array methods (such as `.forEach()`) if `thisArg` is given.
      * @param {ASTNode} node A function node to check.
      * @param {SourceCode} sourceCode A SourceCode instance to get comments.
+     * @param {boolean} [capIsConstructor = true] `false` disables the assumption that functions which name starts
+     * with an uppercase or are assigned to a variable which name starts with an uppercase are constructors.
      * @returns {boolean} The function node is the default `this` binding.
      */
-    isDefaultThisBinding(node, sourceCode) {
-        if (isES5Constructor(node) || hasJSDocThisTag(node, sourceCode)) {
+    isDefaultThisBinding(node, sourceCode, { capIsConstructor = true } = {}) {
+        if (
+            (capIsConstructor && isES5Constructor(node)) ||
+            hasJSDocThisTag(node, sourceCode)
+        ) {
             return false;
         }
         const isAnonymous = node.id === null;
@@ -671,6 +679,7 @@ module.exports = {
                         return false;
                     }
                     if (
+                        capIsConstructor &&
                         isAnonymous &&
                         parent.left.type === "Identifier" &&
                         startsWithUpperCase(parent.left.name)
@@ -685,6 +694,7 @@ module.exports = {
                  */
                 case "VariableDeclarator":
                     return !(
+                        capIsConstructor &&
                         isAnonymous &&
                         parent.init === currentNode &&
                         parent.id.type === "Identifier" &&
diff --git a/package.json b/package.json
index 778365194..fdadc5d43 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "6.5.1",
+  "version": "6.6.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -52,15 +52,15 @@
     "debug": "^4.0.1",
     "doctrine": "^3.0.0",
     "eslint-scope": "^5.0.0",
-    "eslint-utils": "^1.4.2",
+    "eslint-utils": "^1.4.3",
     "eslint-visitor-keys": "^1.1.0",
-    "espree": "^6.1.1",
+    "espree": "^6.1.2",
     "esquery": "^1.0.1",
     "esutils": "^2.0.2",
     "file-entry-cache": "^5.0.1",
     "functional-red-black-tree": "^1.0.1",
     "glob-parent": "^5.0.0",
-    "globals": "^11.7.0",
+    "globals": "^12.1.0",
     "ignore": "^4.0.6",
     "import-fresh": "^3.0.0",
     "imurmurhash": "^0.1.4",
@@ -86,7 +86,7 @@
   "devDependencies": {
     "@babel/core": "^7.4.3",
     "@babel/preset-env": "^7.4.3",
-    "acorn": "^7.0.0",
+    "acorn": "^7.1.0",
     "babel-loader": "^8.0.5",
     "chai": "^4.0.1",
     "cheerio": "^0.22.0",
diff --git a/tools/rule-types.json b/tools/rule-types.json
index 6c72abb6c..4bc07d4e4 100644
--- a/tools/rule-types.json
+++ b/tools/rule-types.json
@@ -225,6 +225,7 @@
     "prefer-arrow-callback": "suggestion",
     "prefer-const": "suggestion",
     "prefer-destructuring": "suggestion",
+    "prefer-exponentiation-operator": "suggestion",
     "prefer-named-capture-group": "suggestion",
     "prefer-numeric-literals": "suggestion",
     "prefer-object-spread": "suggestion",


Test patch:
diff --git a/tests/lib/cli-engine/cli-engine.js b/tests/lib/cli-engine/cli-engine.js
index 7c2ce871c..2cdc81301 100644
--- a/tests/lib/cli-engine/cli-engine.js
+++ b/tests/lib/cli-engine/cli-engine.js
@@ -4022,6 +4022,14 @@ describe("CLIEngine", () => {
 
             assert(engine.getRules().has("node/no-deprecated-api"), "node/no-deprecated-api is present");
         });
+
+        it("should expose the rules of the plugin that is added by 'addPlugin'.", () => {
+            const engine = new CLIEngine({ plugins: ["foo"] });
+
+            engine.addPlugin("foo", require("eslint-plugin-node"));
+
+            assert(engine.getRules().has("foo/no-deprecated-api"), "foo/no-deprecated-api is present");
+        });
     });
 
     describe("resolveFileGlobPatterns", () => {
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index 573c0c2bd..6d51825eb 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -235,31 +235,100 @@ ruleTester.run("comma-dangle", rule, {
             options: ["only-multiline"],
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
         },
-
-
-        // trailing comma in functions -- ignore by default
         {
-            code: "function foo(a,) {}",
+            code: "function foo(a) {}",
+            options: ["always"]
+        },
+        {
+            code: "foo(a)",
+            options: ["always"]
+        },
+        {
+            code: "function foo(a) {}",
+            options: ["never"]
+        },
+        {
+            code: "foo(a)",
+            options: ["never"]
+        },
+        {
+            code: "function foo(a,\nb) {}",
+            options: ["always-multiline"]
+        },
+        {
+            code: "foo(a,\nb)",
+            options: ["always-multiline"]
+        },
+        {
+            code: "function foo(a,\nb) {}",
+            options: ["only-multiline"]
+        },
+        {
+            code: "foo(a,\nb)",
+            options: ["only-multiline"]
+        },
+        {
+            code: "function foo(a) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "foo(a)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "function foo(a) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "foo(a)",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "function foo(a,\nb) {}",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "foo(a,\nb)",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "function foo(a,\nb) {}",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "foo(a,\nb)",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 7 }
+        },
+        {
+            code: "function foo(a) {}",
             options: ["never"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "foo(a,)",
+            code: "foo(a)",
             options: ["never"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "function foo(a) {}",
+            code: "function foo(a,) {}",
             options: ["always"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "foo(a)",
+            code: "foo(a,)",
             options: ["always"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "function foo(\na,\nb\n) {}",
+            code: "function foo(\na,\nb,\n) {}",
             options: ["always-multiline"],
             parserOptions: { ecmaVersion: 8 }
         },
@@ -269,22 +338,22 @@ ruleTester.run("comma-dangle", rule, {
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "function foo(a,b,) {}",
+            code: "function foo(a,b) {}",
             options: ["always-multiline"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "foo(a,b,)",
+            code: "foo(a,b)",
             options: ["always-multiline"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "function foo(a,b,) {}",
+            code: "function foo(a,b) {}",
             options: ["only-multiline"],
             parserOptions: { ecmaVersion: 8 }
         },
         {
-            code: "foo(a,b,)",
+            code: "foo(a,b)",
             options: ["only-multiline"],
             parserOptions: { ecmaVersion: 8 }
         },
@@ -315,6 +384,11 @@ ruleTester.run("comma-dangle", rule, {
             options: [{ functions: "always" }],
             parserOptions: { ecmaVersion: 8 }
         },
+        {
+            code: "foo(a,)",
+            options: [{ functions: "always" }],
+            parserOptions: { ecmaVersion: 9 }
+        },
         {
             code: "bar(...a,)",
             options: [{ functions: "always" }],
@@ -1283,6 +1357,208 @@ ruleTester.run("comma-dangle", rule, {
             parserOptions: { ecmaVersion: 8 },
             errors: [{ messageId: "unexpected", type: "SpreadElement" }]
         },
+        {
+            code: "function foo(a,) {}",
+            output: "function foo(a) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "(function foo(a,) {})",
+            output: "(function foo(a) {})",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "(a,) => a",
+            output: "(a) => a",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "(a,) => (a)",
+            output: "(a) => (a)",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "({foo(a,) {}})",
+            output: "({foo(a) {}})",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "class A {foo(a,) {}}",
+            output: "class A {foo(a) {}}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(a,)",
+            output: "foo(a)",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(...a,)",
+            output: "foo(...a)",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "SpreadElement" }]
+        },
+
+        {
+            code: "function foo(a) {}",
+            output: "function foo(a,) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "(function foo(a) {})",
+            output: "(function foo(a,) {})",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "(a) => a",
+            output: "(a,) => a",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "(a) => (a)",
+            output: "(a,) => (a)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "({foo(a) {}})",
+            output: "({foo(a,) {},})",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [
+                { messageId: "missing", type: "Identifier" },
+                { messageId: "missing", type: "Property" }
+            ]
+        },
+        {
+            code: "class A {foo(a) {}}",
+            output: "class A {foo(a,) {}}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "foo(a)",
+            output: "foo(a,)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "foo(...a)",
+            output: "foo(...a,)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "SpreadElement" }]
+        },
+
+        {
+            code: "function foo(a,) {}",
+            output: "function foo(a) {}",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "(function foo(a,) {})",
+            output: "(function foo(a) {})",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(a,)",
+            output: "foo(a)",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(...a,)",
+            output: "foo(...a)",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "SpreadElement" }]
+        },
+        {
+            code: "function foo(\na,\nb\n) {}",
+            output: "function foo(\na,\nb,\n) {}",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "foo(\na,\nb\n)",
+            output: "foo(\na,\nb,\n)",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
+        {
+            code: "foo(\n...a,\n...b\n)",
+            output: "foo(\n...a,\n...b,\n)",
+            options: ["always-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "missing", type: "SpreadElement" }]
+        },
+
+        {
+            code: "function foo(a,) {}",
+            output: "function foo(a) {}",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "(function foo(a,) {})",
+            output: "(function foo(a) {})",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(a,)",
+            output: "foo(a)",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "Identifier" }]
+        },
+        {
+            code: "foo(...a,)",
+            output: "foo(...a)",
+            options: ["only-multiline"],
+            parserOptions: { ecmaVersion: 8 },
+            errors: [{ messageId: "unexpected", type: "SpreadElement" }]
+        },
+        {
+            code: "function foo(a) {}",
+            output: "function foo(a,) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 9 },
+            errors: [{ messageId: "missing", type: "Identifier" }]
+        },
 
         // separated options
         {
diff --git a/tests/lib/rules/function-call-argument-newline.js b/tests/lib/rules/function-call-argument-newline.js
index 2871534e7..6a5b739af 100644
--- a/tests/lib/rules/function-call-argument-newline.js
+++ b/tests/lib/rules/function-call-argument-newline.js
@@ -46,6 +46,8 @@ ruleTester.run("function-call-argument-newline", rule, {
             options: ["always"],
             parserOptions: { ecmaVersion: 6 }
         },
+        { code: "fn({\n\ta: 1\n},\n\tb,\n\tc)", options: ["always"] },
+        { code: "fn(`\n`,\n\ta)", options: ["always"], parserOptions: { ecmaVersion: 6 } },
 
         /* "never" */
         { code: "fn(a, b)", options: ["never"] },
@@ -59,10 +61,16 @@ ruleTester.run("function-call-argument-newline", rule, {
             options: ["never"],
             parserOptions: { ecmaVersion: 6 }
         },
+        { code: "fn({\n\ta: 1\n}, b)", options: ["never"] },
+        { code: "fn(`\n`, a)", options: ["never"], parserOptions: { ecmaVersion: 6 } },
 
         /* "consistent" */
         { code: "fn(a, b, c)", options: ["consistent"] },
-        { code: "fn(a,\n\tb,\n\tc)", options: ["consistent"] }
+        { code: "fn(a,\n\tb,\n\tc)", options: ["consistent"] },
+        { code: "fn({\n\ta: 1\n}, b, c)", options: ["consistent"] },
+        { code: "fn({\n\ta: 1\n},\n\tb,\n\tc)", options: ["consistent"] },
+        { code: "fn(`\n`, b, c)", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        { code: "fn(`\n`,\n\tb,\n\tc)", options: ["consistent"], parserOptions: { ecmaVersion: 6 } }
     ],
     invalid: [
 
@@ -202,6 +210,35 @@ ruleTester.run("function-call-argument-newline", rule, {
                 }
             ]
         },
+        {
+            code: "fn({\n\ta: 1\n}, b)",
+            output: "fn({\n\ta: 1\n},\nb)",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 3,
+                    column: 3,
+                    endLine: 3,
+                    endColumn: 4
+                }
+            ]
+        },
+        {
+            code: "fn(`\n`, b)",
+            output: "fn(`\n`,\nb)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 2,
+                    column: 3,
+                    endLine: 2,
+                    endColumn: 4
+                }
+            ]
+        },
 
         /* "never" */
         {
@@ -324,6 +361,35 @@ ruleTester.run("function-call-argument-newline", rule, {
                 }
             ]
         },
+        {
+            code: "fn({\n\ta: 1\n},\nb)",
+            output: "fn({\n\ta: 1\n}, b)",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 3,
+                    column: 3,
+                    endLine: 4,
+                    endColumn: 1
+                }
+            ]
+        },
+        {
+            code: "fn(`\n`,\nb)",
+            output: "fn(`\n`, b)",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 3,
+                    endLine: 3,
+                    endColumn: 1
+                }
+            ]
+        },
 
         /* "consistent" */
         {
@@ -381,6 +447,64 @@ ruleTester.run("function-call-argument-newline", rule, {
                     endColumn: 19
                 }
             ]
+        },
+        {
+            code: "fn({\n\ta: 1\n},\nb, c)",
+            output: "fn({\n\ta: 1\n},\nb,\nc)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 4,
+                    column: 3,
+                    endLine: 4,
+                    endColumn: 4
+                }
+            ]
+        },
+        {
+            code: "fn({\n\ta: 1\n}, b,\nc)",
+            output: "fn({\n\ta: 1\n}, b, c)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 3,
+                    column: 6,
+                    endLine: 4,
+                    endColumn: 1
+                }
+            ]
+        },
+        {
+            code: "fn(`\n`,\nb, c)",
+            output: "fn(`\n`,\nb,\nc)",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 3,
+                    column: 3,
+                    endLine: 3,
+                    endColumn: 4
+                }
+            ]
+        },
+        {
+            code: "fn(`\n`, b,\nc)",
+            output: "fn(`\n`, b, c)",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 6,
+                    endLine: 3,
+                    endColumn: 1
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/no-cond-assign.js b/tests/lib/rules/no-cond-assign.js
index 39af0eed2..372b81c1b 100644
--- a/tests/lib/rules/no-cond-assign.js
+++ b/tests/lib/rules/no-cond-assign.js
@@ -41,7 +41,10 @@ ruleTester.run("no-cond-assign", rule, {
         { code: "if (function(node) { return node = parentNode; }) { }", options: ["except-parens"] },
         { code: "if (function(node) { return node = parentNode; }) { }", options: ["always"] },
         { code: "x = 0;", options: ["always"] },
-        "var x; var b = (x === 0) ? 1 : 0;"
+        "var x; var b = (x === 0) ? 1 : 0;",
+        { code: "switch (foo) { case a = b: bar(); }", options: ["except-parens"] },
+        { code: "switch (foo) { case a = b: bar(); }", options: ["always"] },
+        { code: "switch (foo) { case baz + (a = b): bar(); }", options: ["always"] }
     ],
     invalid: [
         { code: "var x; if (x = 0) { var b = 1; }", errors: [{ messageId: "missing", type: "IfStatement", line: 1, column: 12 }] },
@@ -62,6 +65,7 @@ ruleTester.run("no-cond-assign", rule, {
         { code: "do { } while ((x = x + 1));", options: ["always"], errors: [{ messageId: "unexpected", data: { type: "a 'do...while' statement" }, type: "DoWhileStatement" }] },
         { code: "for(; (x = y); ) { }", options: ["always"], errors: [{ messageId: "unexpected", data: { type: "a 'for' statement" }, type: "ForStatement" }] },
         { code: "var x; var b = (x = 0) ? 1 : 0;", errors: [{ messageId: "missing", type: "ConditionalExpression" }] },
+        { code: "var x; var b = x && (y = 0) ? 1 : 0;", options: ["always"], errors: [{ messageId: "unexpected", type: "ConditionalExpression" }] },
         { code: "(((3496.29)).bkufyydt = 2e308) ? foo : bar;", errors: [{ messageId: "missing", type: "ConditionalExpression" }] }
     ]
 });
diff --git a/tests/lib/rules/no-inline-comments.js b/tests/lib/rules/no-inline-comments.js
index 6af30d12b..6a6f5a8ef 100644
--- a/tests/lib/rules/no-inline-comments.js
+++ b/tests/lib/rules/no-inline-comments.js
@@ -15,7 +15,13 @@ const rule = require("../../../lib/rules/no-inline-comments"),
 // Tests
 //------------------------------------------------------------------------------
 
-const ruleTester = new RuleTester(),
+const ruleTester = new RuleTester({
+        parserOptions: {
+            ecmaFeatures: {
+                jsx: true
+            }
+        }
+    }),
     lineError = {
         message: "Unexpected comment inline with code.",
         type: "Line"
@@ -32,7 +38,57 @@ ruleTester.run("no-inline-comments", rule, {
         "var a = 2;\n// A valid comment after code",
         "// A solitary comment",
         "var a = 1; // eslint-disable-line no-debugger",
-        "var a = 1; /* eslint-disable-line no-debugger */"
+        "var a = 1; /* eslint-disable-line no-debugger */",
+
+        // JSX exception
+        `var a = (
+            <div>
+            {/*comment*/}
+            </div>
+        )`,
+        `var a = (
+            <div>
+            { /* comment */ }
+            <h1>Some heading</h1>
+            </div>
+        )`,
+        `var a = (
+            <div>
+            {// comment
+            }
+            </div>
+        )`,
+        `var a = (
+            <div>
+            { // comment
+            }
+            </div>
+        )`,
+        `var a = (
+            <div>
+            {/* comment 1 */
+            /* comment 2 */}
+            </div>
+        )`,
+        `var a = (
+            <div>
+            {/*
+              * comment 1
+              */
+             /*
+              * comment 2
+              */}
+            </div>
+        )`,
+        `var a = (
+            <div>
+            {/*
+               multi
+               line
+               comment
+            */}
+            </div>
+        )`
     ],
 
     invalid: [
@@ -55,7 +111,240 @@ ruleTester.run("no-inline-comments", rule, {
         {
             code: "var a = 4;\n/**A\n * block\n * comment\n * inline\n * between\n * code*/ var foo = a;",
             errors: [blockError]
+        },
+        {
+            code: "var a = \n{/**/}",
+            errors: [blockError]
+        },
+
+        // JSX
+        {
+            code: `var a = (
+                <div>{/* comment */}</div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>{// comment
+                }
+                </div>
+            )`,
+            errors: [lineError]
+        },
+        {
+            code: `var a = (
+                <div>{/* comment */
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>{/*
+                       * comment
+                       */
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>{/*
+                       * comment
+                       */}
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>{/*
+                       * comment
+                       */}</div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {/*
+                  * comment
+                  */}</div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                 /*
+                  * comment
+                  */}</div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                /* comment */}</div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {b/* comment */}
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {/* comment */b}
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {// comment
+                    b
+                }
+                </div>
+            )`,
+            errors: [lineError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {/* comment */
+                    b
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {/*
+                  * comment
+                  */
+                    b
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    b// comment
+                }
+                </div>
+            )`,
+            errors: [lineError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    /* comment */b
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    b/* comment */
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    b
+                /*
+                 * comment
+                 */}
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    b
+                /* comment */}
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    { /* this is an empty object literal, not braces for js code! */ }
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    {// comment
+                    }
+                }
+                </div>
+            )`,
+            errors: [lineError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    {
+                    /* comment */}
+                }
+                </div>
+            )`,
+            errors: [blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                { /* two comments on the same line... */ /* ...are not allowed, same as with a non-JSX code */}
+                </div>
+            )`,
+            errors: [blockError, blockError]
+        },
+        {
+            code: `var a = (
+                <div>
+                {
+                    /* overlapping
+                    */ /*
+                       lines */
+                }
+                </div>
+            )`,
+            errors: [blockError, blockError]
         }
     ]
-
 });
diff --git a/tests/lib/rules/no-invalid-this.js b/tests/lib/rules/no-invalid-this.js
index e4606d0e6..24b95405b 100644
--- a/tests/lib/rules/no-invalid-this.js
+++ b/tests/lib/rules/no-invalid-this.js
@@ -134,6 +134,22 @@ const patterns = [
         valid: [NORMAL],
         invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
     },
+    {
+        code: "function foo() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }], // test that the option doesn't reverse the logic and mistakenly allows lowercase functions
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
+    {
+        code: "function Foo() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
     {
         code: "function foo() { \"use strict\"; console.log(this); z(x => console.log(x, this)); }",
         parserOptions: { ecmaVersion: 6 },
@@ -141,6 +157,14 @@ const patterns = [
         valid: [],
         invalid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES]
     },
+    {
+        code: "function Foo() { \"use strict\"; console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
+        errors,
+        valid: [],
+        invalid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
     {
         code: "return function() { console.log(this); z(x => console.log(x, this)); };",
         parserOptions: {
@@ -226,6 +250,20 @@ const patterns = [
         valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
         invalid: []
     },
+    {
+        code: "function Foo() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{}], // test the default value in schema
+        valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
+        invalid: []
+    },
+    {
+        code: "function Foo() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: true }], // test explicitly set option to the default value
+        valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
+        invalid: []
+    },
     {
         code: "var Foo = function Foo() { console.log(this); z(x => console.log(x, this)); };",
         parserOptions: { ecmaVersion: 6 },
@@ -556,9 +594,25 @@ const patterns = [
         valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
         invalid: []
     },
+    {
+        code: "var Ctor = function() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
+    {
+        code: "var func = function() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
     {
         code: "var func = function() { console.log(this); z(x => console.log(x, this)); }",
         parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
         errors,
         valid: [NORMAL],
         invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
@@ -569,9 +623,25 @@ const patterns = [
         valid: [NORMAL, USE_STRICT, IMPLIED_STRICT, MODULES],
         invalid: []
     },
+    {
+        code: "Ctor = function() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
+    {
+        code: "func = function() { console.log(this); z(x => console.log(x, this)); }",
+        parserOptions: { ecmaVersion: 6 },
+        errors,
+        valid: [NORMAL],
+        invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
+    },
     {
         code: "func = function() { console.log(this); z(x => console.log(x, this)); }",
         parserOptions: { ecmaVersion: 6 },
+        options: [{ capIsConstructor: false }],
         errors,
         valid: [NORMAL],
         invalid: [USE_STRICT, IMPLIED_STRICT, MODULES]
diff --git a/tests/lib/rules/no-misleading-character-class.js b/tests/lib/rules/no-misleading-character-class.js
index 4eb104fc6..b4b3ac530 100644
--- a/tests/lib/rules/no-misleading-character-class.js
+++ b/tests/lib/rules/no-misleading-character-class.js
@@ -63,7 +63,11 @@ ruleTester.run("no-misleading-character-class", rule, {
 
         // Ignore solo ZWJ.
         "var r = /[\\u200D]/",
-        "var r = /[\\u200D]/u"
+        "var r = /[\\u200D]/u",
+
+        // don't report and don't crash on invalid regex
+        "var r = new RegExp('[Á] [ ');",
+        "var r = RegExp('{ [Á]', 'u');"
     ],
     invalid: [
 
diff --git a/tests/lib/rules/no-obj-calls.js b/tests/lib/rules/no-obj-calls.js
index d5bcf0638..db7261568 100644
--- a/tests/lib/rules/no-obj-calls.js
+++ b/tests/lib/rules/no-obj-calls.js
@@ -61,6 +61,10 @@ ruleTester.run("no-obj-calls", rule, {
         {
             code: "function foo() { var Atomics = bar(); var baz = Atomics(5); }",
             globals: { Atomics: false }
+        },
+        {
+            code: "var construct = typeof Reflect !== \"undefined\" ? Reflect.construct : undefined; construct();",
+            globals: { Reflect: false }
         }
     ],
     invalid: [
diff --git a/tests/lib/rules/no-param-reassign.js b/tests/lib/rules/no-param-reassign.js
index fec1e4168..5bb70e6aa 100644
--- a/tests/lib/rules/no-param-reassign.js
+++ b/tests/lib/rules/no-param-reassign.js
@@ -45,6 +45,11 @@ ruleTester.run("no-param-reassign", rule, {
         { code: "function foo(a) { for (a.b of arr); }", options: [{ props: true, ignorePropertyModificationsFor: ["a"] }], parserOptions: { ecmaVersion: 6 } },
         { code: "function foo(a, z) { a.b = 0; x.y = 0; }", options: [{ props: true, ignorePropertyModificationsFor: ["a", "x"] }] },
         { code: "function foo(a) { a.b.c = 0;}", options: [{ props: true, ignorePropertyModificationsFor: ["a"] }] },
+        { code: "function foo(aFoo) { aFoo.b = 0; }", options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$"] }] },
+        { code: "function foo(aFoo) { ++aFoo.b; }", options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$"] }] },
+        { code: "function foo(aFoo) { delete aFoo.b; }", options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$"] }] },
+        { code: "function foo(a, z) { aFoo.b = 0; x.y = 0; }", options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$", "^x.*$"] }] },
+        { code: "function foo(aFoo) { aFoo.b.c = 0;}", options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$"] }] },
         {
             code: "function foo(a) { ({ [a]: variable } = value) }",
             options: [{ props: true }],
@@ -152,6 +157,18 @@ ruleTester.run("no-param-reassign", rule, {
             parserOptions: { ecmaVersion: 6 },
             errors: [{ message: "Assignment to property of function parameter 'bar'." }]
         },
+        {
+            code: "function foo(bar) { [bar.a] = []; }",
+            options: [{ props: true, ignorePropertyModificationsForRegex: ["^a.*$"] }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Assignment to property of function parameter 'bar'." }]
+        },
+        {
+            code: "function foo(bar) { [bar.a] = []; }",
+            options: [{ props: true, ignorePropertyModificationsForRegex: ["^B.*$"] }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Assignment to property of function parameter 'bar'." }]
+        },
         {
             code: "function foo(bar) { ({foo: bar.a} = {}); }",
             options: [{ props: true }],
diff --git a/tests/lib/rules/no-tabs.js b/tests/lib/rules/no-tabs.js
index ac0ad9e74..637f49051 100644
--- a/tests/lib/rules/no-tabs.js
+++ b/tests/lib/rules/no-tabs.js
@@ -40,7 +40,9 @@ ruleTester.run("no-tabs", rule, {
             errors: [{
                 message: ERROR_MESSAGE,
                 line: 1,
-                column: 17
+                column: 17,
+                endLine: 1,
+                endColumn: 18
             }]
         },
         {
@@ -48,7 +50,9 @@ ruleTester.run("no-tabs", rule, {
             errors: [{
                 message: ERROR_MESSAGE,
                 line: 1,
-                column: 5
+                column: 5,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -59,7 +63,9 @@ ruleTester.run("no-tabs", rule, {
             errors: [{
                 message: ERROR_MESSAGE,
                 line: 2,
-                column: 5
+                column: 5,
+                endLine: 2,
+                endColumn: 6
             }]
         },
         {
@@ -70,7 +76,9 @@ ruleTester.run("no-tabs", rule, {
             errors: [{
                 message: ERROR_MESSAGE,
                 line: 1,
-                column: 9
+                column: 9,
+                endLine: 1,
+                endColumn: 10
             }]
         },
         {
@@ -82,12 +90,16 @@ ruleTester.run("no-tabs", rule, {
                 {
                     message: ERROR_MESSAGE,
                     line: 2,
-                    column: 5
+                    column: 5,
+                    endLine: 2,
+                    endColumn: 6
                 },
                 {
                     message: ERROR_MESSAGE,
                     line: 3,
-                    column: 1
+                    column: 1,
+                    endLine: 3,
+                    endColumn: 2
                 }
             ]
         },
@@ -97,8 +109,50 @@ ruleTester.run("no-tabs", rule, {
             errors: [{
                 message: ERROR_MESSAGE,
                 line: 1,
-                column: 30
+                column: 30,
+                endLine: 1,
+                endColumn: 31
             }]
+        },
+        {
+            code: "\t\ta =\t\t\tb +\tc\t\t;\t\t",
+            errors: [
+                {
+                    message: ERROR_MESSAGE,
+                    line: 1,
+                    column: 1,
+                    endLine: 1,
+                    endColumn: 3
+                },
+                {
+                    message: ERROR_MESSAGE,
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 9
+                },
+                {
+                    message: ERROR_MESSAGE,
+                    line: 1,
+                    column: 12,
+                    endLine: 1,
+                    endColumn: 13
+                },
+                {
+                    message: ERROR_MESSAGE,
+                    line: 1,
+                    column: 14,
+                    endLine: 1,
+                    endColumn: 16
+                },
+                {
+                    message: ERROR_MESSAGE,
+                    line: 1,
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 19
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/no-trailing-spaces.js b/tests/lib/rules/no-trailing-spaces.js
index 3120b4a71..b1ff90ea2 100644
--- a/tests/lib/rules/no-trailing-spaces.js
+++ b/tests/lib/rules/no-trailing-spaces.js
@@ -86,6 +86,14 @@ ruleTester.run("no-trailing-spaces", rule, {
         {
             code: "#!/usr/bin/env node ",
             options: [{ ignoreComments: true }]
+        },
+        {
+            code: "/* \n */ // ",
+            options: [{ ignoreComments: true }]
+        },
+        {
+            code: "/* \n */ /* \n */",
+            options: [{ ignoreComments: true }]
         }
     ],
 
@@ -268,12 +276,16 @@ ruleTester.run("no-trailing-spaces", rule, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 1,
-                column: 11
+                column: 11,
+                endLine: 1,
+                endColumn: 12
             }, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 2,
-                column: 8
+                column: 8,
+                endLine: 2,
+                endColumn: 9
             }]
         },
         {
@@ -284,7 +296,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 1,
-                column: 11
+                column: 11,
+                endLine: 1,
+                endColumn: 12
             }]
         },
         {
@@ -295,7 +309,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 1,
-                column: 1
+                column: 1,
+                endLine: 1,
+                endColumn: 6
             }]
         },
         {
@@ -317,7 +333,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 1,
-                column: 15 // there are invalid spaces in columns 15 and 16
+                column: 15, // there are invalid spaces in columns 15 and 16
+                endLine: 1,
+                endColumn: 17
             }]
         },
         {
@@ -331,13 +349,17 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 15
+                    column: 15,
+                    endLine: 1,
+                    endColumn: 18
                 },
                 {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 2,
-                    column: 15
+                    column: 15,
+                    endLine: 2,
+                    endColumn: 17
                 }
             ]
         },
@@ -349,7 +371,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                 message: "Trailing spaces not allowed.",
                 type: "Program",
                 line: 3,
-                column: 7
+                column: 7,
+                endLine: 3,
+                endColumn: 9
             }]
         },
         {
@@ -361,13 +385,17 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 4,
-                    column: 7
+                    column: 7,
+                    endLine: 4,
+                    endColumn: 9
                 },
                 {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 5,
-                    column: 1
+                    column: 1,
+                    endLine: 5,
+                    endColumn: 2
                 }
             ]
         },
@@ -380,7 +408,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 4,
-                    column: 7
+                    column: 7,
+                    endLine: 4,
+                    endColumn: 9
                 }
             ]
         },
@@ -396,7 +426,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 3,
-                    column: 7
+                    column: 7,
+                    endLine: 3,
+                    endColumn: 9
                 }
             ]
         },
@@ -411,7 +443,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 2,
-                    column: 8
+                    column: 8,
+                    endLine: 2,
+                    endColumn: 9
                 }
             ]
         },
@@ -423,13 +457,17 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 1
+                    column: 1,
+                    endLine: 1,
+                    endColumn: 5
                 },
                 {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 2,
-                    column: 8
+                    column: 8,
+                    endLine: 2,
+                    endColumn: 9
                 }
             ]
         },
@@ -444,7 +482,61 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 17
+                    column: 17,
+                    endLine: 1,
+                    endColumn: 18
+                }
+            ]
+        },
+        {
+            code: "/* */ ",
+            output: "/* */",
+            options: [{ ignoreComments: true }],
+            errors: [
+                {
+                    message: "Trailing spaces not allowed.",
+                    type: "Program",
+                    line: 1,
+                    column: 6
+                }
+            ]
+        },
+        {
+            code: "/* */foo ",
+            output: "/* */foo",
+            options: [{ ignoreComments: true }],
+            errors: [
+                {
+                    message: "Trailing spaces not allowed.",
+                    type: "Program",
+                    line: 1,
+                    column: 9
+                }
+            ]
+        },
+        {
+            code: "/* \n */ ",
+            output: "/* \n */",
+            options: [{ ignoreComments: true }],
+            errors: [
+                {
+                    message: "Trailing spaces not allowed.",
+                    type: "Program",
+                    line: 2,
+                    column: 4
+                }
+            ]
+        },
+        {
+            code: "/* \n */ foo ",
+            output: "/* \n */ foo",
+            options: [{ ignoreComments: true }],
+            errors: [
+                {
+                    message: "Trailing spaces not allowed.",
+                    type: "Program",
+                    line: 2,
+                    column: 8
                 }
             ]
         },
@@ -457,7 +549,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 26
+                    column: 26,
+                    endLine: 1,
+                    endColumn: 27
                 }
             ]
         },
@@ -470,13 +564,17 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 3
+                    column: 3,
+                    endLine: 1,
+                    endColumn: 4
                 },
                 {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 2,
-                    column: 24
+                    column: 24,
+                    endLine: 2,
+                    endColumn: 25
                 }
             ]
         },
@@ -489,7 +587,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 20
+                    column: 20,
+                    endLine: 1,
+                    endColumn: 21
                 }
             ]
         },
@@ -502,7 +602,9 @@ ruleTester.run("no-trailing-spaces", rule, {
                     message: "Trailing spaces not allowed.",
                     type: "Program",
                     line: 1,
-                    column: 34
+                    column: 34,
+                    endLine: 1,
+                    endColumn: 35
                 }
             ]
         }
diff --git a/tests/lib/rules/no-underscore-dangle.js b/tests/lib/rules/no-underscore-dangle.js
index 277c6c85c..b3774dc18 100644
--- a/tests/lib/rules/no-underscore-dangle.js
+++ b/tests/lib/rules/no-underscore-dangle.js
@@ -38,7 +38,8 @@ ruleTester.run("no-underscore-dangle", rule, {
         { code: "const o = { _onClick() { } }", parserOptions: { ecmaVersion: 6 } },
         { code: "const o = { onClick_() { } }", parserOptions: { ecmaVersion: 6 } },
         { code: "const o = { _foo: 'bar' }", parserOptions: { ecmaVersion: 6 } },
-        { code: "const o = { foo_: 'bar' }", parserOptions: { ecmaVersion: 6 } }
+        { code: "const o = { foo_: 'bar' }", parserOptions: { ecmaVersion: 6 } },
+        { code: "this.constructor._bar", options: [{ allowAfterThisConstructor: true }] }
     ],
     invalid: [
         { code: "var _foo = 1", errors: [{ message: "Unexpected dangling '_' in '_foo'.", type: "VariableDeclarator" }] },
@@ -53,6 +54,8 @@ ruleTester.run("no-underscore-dangle", rule, {
         { code: "class foo { _onClick() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_onClick'.", type: "MethodDefinition" }] },
         { code: "class foo { onClick_() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in 'onClick_'.", type: "MethodDefinition" }] },
         { code: "const o = { _onClick() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in '_onClick'.", type: "Property" }] },
-        { code: "const o = { onClick_() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in 'onClick_'.", type: "Property" }] }
+        { code: "const o = { onClick_() { } }", options: [{ enforceInMethodNames: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Unexpected dangling '_' in 'onClick_'.", type: "Property" }] },
+        { code: "this.constructor._bar", errors: [{ message: "Unexpected dangling '_' in '_bar'.", type: "MemberExpression" }] },
+        { code: "foo.constructor._bar", options: [{ allowAfterThisConstructor: true }], errors: [{ message: "Unexpected dangling '_' in '_bar'.", type: "MemberExpression" }] }
     ]
 });
diff --git a/tests/lib/rules/no-unneeded-ternary.js b/tests/lib/rules/no-unneeded-ternary.js
index 243526c22..a297b211b 100644
--- a/tests/lib/rules/no-unneeded-ternary.js
+++ b/tests/lib/rules/no-unneeded-ternary.js
@@ -27,6 +27,12 @@ ruleTester.run("no-unneeded-ternary", rule, {
         "var a = x === 2 ? 'true' : 'false';",
         "var a = foo ? foo : bar;",
         "var value = 'a';var canSet = true;var result = value || (canSet ? 'unset' : 'can not set')",
+        "var a = foo ? bar : foo;",
+        "foo ? bar : foo;",
+        "var a = f(x ? x : 1)",
+        "f(x ? x : 1);",
+        "foo ? foo : bar;",
+        "var a = foo ? 'Yes' : foo;",
         {
             code: "var a = foo ? 'Yes' : foo;",
             options: [{ defaultAssignment: false }]
@@ -34,6 +40,10 @@ ruleTester.run("no-unneeded-ternary", rule, {
         {
             code: "var a = foo ? bar : foo;",
             options: [{ defaultAssignment: false }]
+        },
+        {
+            code: "foo ? bar : foo;",
+            options: [{ defaultAssignment: false }]
         }
     ],
     invalid: [
@@ -314,6 +324,39 @@ ruleTester.run("no-unneeded-ternary", rule, {
                 line: 1,
                 column: 13
             }]
+        },
+        {
+            code: "f(x ? x : 1);",
+            output: "f(x || 1);",
+            options: [{ defaultAssignment: false }],
+            errors: [{
+                message: "Unnecessary use of conditional expression for default assignment.",
+                type: "ConditionalExpression",
+                line: 1,
+                column: 7
+            }]
+        },
+        {
+            code: "x ? x : 1;",
+            output: "x || 1;",
+            options: [{ defaultAssignment: false }],
+            errors: [{
+                message: "Unnecessary use of conditional expression for default assignment.",
+                type: "ConditionalExpression",
+                line: 1,
+                column: 5
+            }]
+        },
+        {
+            code: "var a = foo ? foo : bar;",
+            output: "var a = foo || bar;",
+            options: [{ defaultAssignment: false }],
+            errors: [{
+                message: "Unnecessary use of conditional expression for default assignment.",
+                type: "ConditionalExpression",
+                line: 1,
+                column: 15
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-unsafe-negation.js b/tests/lib/rules/no-unsafe-negation.js
index 6ac245412..9493bbb72 100644
--- a/tests/lib/rules/no-unsafe-negation.js
+++ b/tests/lib/rules/no-unsafe-negation.js
@@ -18,7 +18,26 @@ 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 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: [
@@ -29,7 +48,37 @@ ruleTester.run("no-unsafe-negation", rule, {
         "a instanceof b",
         "a instanceof b === false",
         "!(a instanceof b)",
-        "(!a) instanceof b"
+        "(!a) instanceof b",
+
+        // tests cases for enforceForOrderingRelations option:
+        "if (! a < b) {}",
+        "while (! a > b) {}",
+        "foo = ! a <= b;",
+        "foo = ! a >= b;",
+        {
+            code: "! a <= b",
+            options: [{}]
+        },
+        {
+            code: "foo = ! a >= b;",
+            options: [{ enforceForOrderingRelations: false }]
+        },
+        {
+            code: "foo = (!a) >= b;",
+            options: [{ enforceForOrderingRelations: true }]
+        },
+        {
+            code: "a <= b",
+            options: [{ enforceForOrderingRelations: true }]
+        },
+        {
+            code: "!(a < b)",
+            options: [{ enforceForOrderingRelations: true }]
+        },
+        {
+            code: "foo = a > b;",
+            options: [{ enforceForOrderingRelations: true }]
+        }
     ],
     invalid: [
         {
@@ -55,6 +104,31 @@ ruleTester.run("no-unsafe-negation", rule, {
         {
             code: "!(a) instanceof b",
             errors: [unexpectedInstanceofError]
+        },
+        {
+            code: "if (! a < b) {}",
+            options: [{ enforceForOrderingRelations: true }],
+            errors: [unexpectedLessThanOperatorError]
+        },
+        {
+            code: "while (! a > b) {}",
+            options: [{ enforceForOrderingRelations: true }],
+            errors: [unexpectedMoreThanOperatorError]
+        },
+        {
+            code: "foo = ! a <= b;",
+            options: [{ enforceForOrderingRelations: true }],
+            errors: [unexpectedLessThanOrEqualOperatorError]
+        },
+        {
+            code: "foo = ! a >= b;",
+            options: [{ enforceForOrderingRelations: true }],
+            errors: [unexpectedMoreThanOrEqualOperatorError]
+        },
+        {
+            code: "! a <= b",
+            options: [{ enforceForOrderingRelations: true }],
+            errors: [unexpectedLessThanOrEqualOperatorError]
         }
     ]
 });
diff --git a/tests/lib/rules/operator-assignment.js b/tests/lib/rules/operator-assignment.js
index fe7b326a1..2f8753253 100644
--- a/tests/lib/rules/operator-assignment.js
+++ b/tests/lib/rules/operator-assignment.js
@@ -191,6 +191,86 @@ ruleTester.run("operator-assignment", rule, {
         code: "foo[5] = foo[5] / baz",
         output: "foo[5] /= baz", // this is ok because 5 is a literal, so toString won't get called
         errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "/*1*/x/*2*/./*3*/y/*4*/= x.y +/*5*/z/*6*/./*7*/w/*8*/;",
+        output: "/*1*/x/*2*/./*3*/y/*4*/+=/*5*/z/*6*/./*7*/w/*8*/;", // these comments are preserved
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x // 1\n . // 2\n y // 3\n = x.y + //4\n z //5\n . //6\n w;",
+        output: "x // 1\n . // 2\n y // 3\n += //4\n z //5\n . //6\n w;", // these comments are preserved
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x = /*1*/ x + y",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x = //1\n x + y",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x.y = x/*1*/.y + z",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x.y = x. //1\n y + z",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x = x /*1*/ + y",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x = x //1\n + y",
+        output: null, // not fixed; fixing would remove this comment
+        options: ["always"],
+        errors: EXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "/*1*/x +=/*2*/y/*3*/;",
+        output: "/*1*/x = x +/*2*/y/*3*/;", // these comments are preserved and not duplicated
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x +=//1\n y",
+        output: "x = x +//1\n y", // this comment is preserved and not duplicated
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "(/*1*/x += y)",
+        output: "(/*1*/x = x + y)", // this comment is preserved and not duplicated
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x/*1*/+=  y",
+        output: null, // not fixed; fixing would duplicate this comment
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x //1\n +=  y",
+        output: null, // not fixed; fixing would duplicate this comment
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "(/*1*/x) +=  y",
+        output: null, // not fixed; fixing would duplicate this comment
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x/*1*/.y +=  z",
+        output: null, // not fixed; fixing would duplicate this comment
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "x.//1\n y +=  z",
+        output: null, // not fixed; fixing would duplicate this comment
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
     }, {
         code: "(foo.bar) ^= ((((((((((((((((baz))))))))))))))))",
         output: "(foo.bar) = (foo.bar) ^ ((((((((((((((((baz))))))))))))))))",
@@ -230,6 +310,31 @@ ruleTester.run("operator-assignment", rule, {
         output: "foo = foo * (bar + 1)",
         options: ["never"],
         errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "foo+=-bar",
+        output: "foo= foo+-bar", // tokens can be adjacent
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "foo+=+bar",
+        output: "foo= foo+ +bar", // tokens cannot be adjacent, insert a space between
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "foo+= +bar",
+        output: "foo= foo+ +bar", // tokens cannot be adjacent, but there is already a space between
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "foo+=/**/+bar",
+        output: "foo= foo+/**/+bar", // tokens cannot be adjacent, but there is a comment between
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
+    }, {
+        code: "foo+=+bar===baz",
+        output: "foo= foo+(+bar===baz)", // tokens cannot be adjacent, but the right side will be parenthesised
+        options: ["never"],
+        errors: UNEXPECTED_OPERATOR_ASSIGNMENT
     }]
 
 });
diff --git a/tests/lib/rules/prefer-exponentiation-operator.js b/tests/lib/rules/prefer-exponentiation-operator.js
new file mode 100644
index 000000000..03d6d5748
--- /dev/null
+++ b/tests/lib/rules/prefer-exponentiation-operator.js
@@ -0,0 +1,309 @@
+/**
+ * @fileoverview Tests for the prefer-exponentiation-operator rule
+ * @author Milos Djermanovic
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/prefer-exponentiation-operator");
+const { RuleTester } = require("../../../lib/rule-tester");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Create an object for the invalid array
+ * @param {string} code source code
+ * @param {string} output fixed source code
+ * @returns {Object} result object
+ * @private
+ */
+function invalid(code, output) {
+    return {
+        code,
+        output,
+        errors: [
+            {
+                messageId: "useExponentiation",
+                type: "CallExpression"
+            }
+        ]
+    };
+}
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 2018 } });
+
+ruleTester.run("prefer-exponentiation-operator", rule, {
+    valid: [
+
+        // not Math.pow()
+        "Object.pow(a, b)",
+        "Math.max(a, b)",
+        "Math",
+        "Math(a, b)",
+        "pow",
+        "pow(a, b)",
+        "Math.pow",
+        "Math.Pow(a, b)",
+        "math.pow(a, b)",
+        "foo.Math.pow(a, b)",
+        "new Math.pow(a, b)",
+        "Math[pow](a, b)",
+
+        // not the global Math
+        "/* globals Math:off*/ Math.pow(a, b)",
+        "let Math; Math.pow(a, b);",
+        "if (foo) { const Math = 1; Math.pow(a, b); }",
+        "var x = function Math() { Math.pow(a, b); }",
+        "function foo(Math) { Math.pow(a, b); }",
+        "function foo() { Math.pow(a, b); var Math; }"
+    ],
+
+    invalid: [
+
+        invalid("Math.pow(a, b)", "a**b"),
+        invalid("(Math).pow(a, b)", "a**b"),
+        invalid("Math['pow'](a, b)", "a**b"),
+        invalid("(Math)['pow'](a, b)", "a**b"),
+        invalid("var x=Math\n.  pow( a, \n b )", "var x=a**b"),
+
+        // able to catch some workarounds
+        invalid("Math[`pow`](a, b)", "a**b"),
+        invalid("Math[`${'pow'}`](a, b)", "a**b"),
+        invalid("Math['p' + 'o' + 'w'](a, b)", "a**b"),
+
+        // non-expression parents that don't require parens
+        invalid("var x = Math.pow(a, b);", "var x = a**b;"),
+        invalid("if(Math.pow(a, b)){}", "if(a**b){}"),
+        invalid("for(;Math.pow(a, b);){}", "for(;a**b;){}"),
+        invalid("switch(foo){ case Math.pow(a, b): break; }", "switch(foo){ case a**b: break; }"),
+        invalid("{ foo: Math.pow(a, b) }", "{ foo: a**b }"),
+        invalid("function foo(bar, baz = Math.pow(a, b), quux){}", "function foo(bar, baz = a**b, quux){}"),
+        invalid("`${Math.pow(a, b)}`", "`${a**b}`"),
+
+        // non-expression parents that do require parens
+        invalid("class C extends Math.pow(a, b) {}", "class C extends (a**b) {}"),
+
+        // parents with a higher precedence
+        invalid("+ Math.pow(a, b)", "+ (a**b)"),
+        invalid("- Math.pow(a, b)", "- (a**b)"),
+        invalid("! Math.pow(a, b)", "! (a**b)"),
+        invalid("typeof Math.pow(a, b)", "typeof (a**b)"),
+        invalid("void Math.pow(a, b)", "void (a**b)"),
+        invalid("Math.pow(a, b) .toString()", "(a**b) .toString()"),
+        invalid("Math.pow(a, b) ()", "(a**b) ()"),
+        invalid("Math.pow(a, b) ``", "(a**b) ``"),
+        invalid("(class extends Math.pow(a, b) {})", "(class extends (a**b) {})"),
+
+        // already parenthesised, shouldn't insert extra parens
+        invalid("+(Math.pow(a, b))", "+(a**b)"),
+        invalid("(Math.pow(a, b)).toString()", "(a**b).toString()"),
+        invalid("(class extends (Math.pow(a, b)) {})", "(class extends (a**b) {})"),
+        invalid("class C extends (Math.pow(a, b)) {}", "class C extends (a**b) {}"),
+
+        // parents with a higher precedence, but the expression's role doesn't require parens
+        invalid("f(Math.pow(a, b))", "f(a**b)"),
+        invalid("f(foo, Math.pow(a, b))", "f(foo, a**b)"),
+        invalid("f(Math.pow(a, b), foo)", "f(a**b, foo)"),
+        invalid("f(foo, Math.pow(a, b), bar)", "f(foo, a**b, bar)"),
+        invalid("new F(Math.pow(a, b))", "new F(a**b)"),
+        invalid("new F(foo, Math.pow(a, b))", "new F(foo, a**b)"),
+        invalid("new F(Math.pow(a, b), foo)", "new F(a**b, foo)"),
+        invalid("new F(foo, Math.pow(a, b), bar)", "new F(foo, a**b, bar)"),
+        invalid("obj[Math.pow(a, b)]", "obj[a**b]"),
+        invalid("[foo, Math.pow(a, b), bar]", "[foo, a**b, bar]"),
+
+        // parents with a lower precedence
+        invalid("a * Math.pow(b, c)", "a * b**c"),
+        invalid("Math.pow(a, b) * c", "a**b * c"),
+        invalid("a + Math.pow(b, c)", "a + b**c"),
+        invalid("Math.pow(a, b)/c", "a**b/c"),
+        invalid("a < Math.pow(b, c)", "a < b**c"),
+        invalid("Math.pow(a, b) > c", "a**b > c"),
+        invalid("a === Math.pow(b, c)", "a === b**c"),
+        invalid("a ? Math.pow(b, c) : d", "a ? b**c : d"),
+        invalid("a = Math.pow(b, c)", "a = b**c"),
+        invalid("a += Math.pow(b, c)", "a += b**c"),
+        invalid("function *f() { yield Math.pow(a, b) }", "function *f() { yield a**b }"),
+        invalid("a, Math.pow(b, c), d", "a, b**c, d"),
+
+        // '**' is right-associative, that applies to both parent and child nodes
+        invalid("a ** Math.pow(b, c)", "a ** b**c"),
+        invalid("Math.pow(a, b) ** c", "(a**b) ** c"),
+        invalid("Math.pow(a, b ** c)", "a**b ** c"),
+        invalid("Math.pow(a ** b, c)", "(a ** b)**c"),
+        invalid("a ** Math.pow(b ** c, d ** e) ** f", "a ** ((b ** c)**d ** e) ** f"),
+
+        // doesn't remove already existing unnecessary parens around the whole expression
+        invalid("(Math.pow(a, b))", "(a**b)"),
+        invalid("foo + (Math.pow(a, b))", "foo + (a**b)"),
+        invalid("(Math.pow(a, b)) + foo", "(a**b) + foo"),
+        invalid("`${(Math.pow(a, b))}`", "`${(a**b)}`"),
+
+        // base and exponent with a higher precedence
+        invalid("Math.pow(2, 3)", "2**3"),
+        invalid("Math.pow(a.foo, b)", "a.foo**b"),
+        invalid("Math.pow(a, b.foo)", "a**b.foo"),
+        invalid("Math.pow(a(), b)", "a()**b"),
+        invalid("Math.pow(a, b())", "a**b()"),
+        invalid("Math.pow(++a, ++b)", "++a**++b"),
+        invalid("Math.pow(a++, ++b)", "a++**++b"),
+        invalid("Math.pow(a--, b--)", "a--**b--"),
+        invalid("Math.pow(--a, b--)", "--a**b--"),
+
+        // doesn't preserve unnecessary parens around base and exponent
+        invalid("Math.pow((a), (b))", "a**b"),
+        invalid("Math.pow(((a)), ((b)))", "a**b"),
+        invalid("Math.pow((a.foo), b)", "a.foo**b"),
+        invalid("Math.pow(a, (b.foo))", "a**b.foo"),
+        invalid("Math.pow((a()), b)", "a()**b"),
+        invalid("Math.pow(a, (b()))", "a**b()"),
+
+        // unary expressions are exception by the language - parens are required for the base to disambiguate operator precedence
+        invalid("Math.pow(+a, b)", "(+a)**b"),
+        invalid("Math.pow(a, +b)", "a**+b"),
+        invalid("Math.pow(-a, b)", "(-a)**b"),
+        invalid("Math.pow(a, -b)", "a**-b"),
+        invalid("Math.pow(-2, 3)", "(-2)**3"),
+        invalid("Math.pow(2, -3)", "2**-3"),
+
+        // base and exponent with a lower precedence
+        invalid("Math.pow(a * b, c)", "(a * b)**c"),
+        invalid("Math.pow(a, b * c)", "a**(b * c)"),
+        invalid("Math.pow(a / b, c)", "(a / b)**c"),
+        invalid("Math.pow(a, b / c)", "a**(b / c)"),
+        invalid("Math.pow(a + b, 3)", "(a + b)**3"),
+        invalid("Math.pow(2, a - b)", "2**(a - b)"),
+        invalid("Math.pow(a + b, c + d)", "(a + b)**(c + d)"),
+        invalid("Math.pow(a = b, c = d)", "(a = b)**(c = d)"),
+        invalid("Math.pow(a += b, c -= d)", "(a += b)**(c -= d)"),
+        invalid("Math.pow((a, b), (c, d))", "(a, b)**(c, d)"),
+        invalid("function *f() { Math.pow(yield, yield) }", "function *f() { (yield)**(yield) }"),
+
+        // doesn't put extra parens
+        invalid("Math.pow((a + b), (c + d))", "(a + b)**(c + d)"),
+
+        // tokens that can be adjacent
+        invalid("a+Math.pow(b, c)+d", "a+b**c+d"),
+
+        // tokens that cannot be adjacent
+        invalid("a+Math.pow(++b, c)", "a+ ++b**c"),
+        invalid("(a)+(Math).pow((++b), c)", "(a)+ ++b**c"),
+        invalid("Math.pow(a, b)in c", "a**b in c"),
+        invalid("Math.pow(a, (b))in (c)", "a**b in (c)"),
+        invalid("a+Math.pow(++b, c)in d", "a+ ++b**c in d"),
+        invalid("a+Math.pow( ++b, c )in d", "a+ ++b**c in d"),
+
+        // tokens that cannot be adjacent, but there is already space or something else between
+        invalid("a+ Math.pow(++b, c) in d", "a+ ++b**c in d"),
+        invalid("a+/**/Math.pow(++b, c)/**/in d", "a+/**/++b**c/**/in d"),
+        invalid("a+(Math.pow(++b, c))in d", "a+(++b**c)in d"),
+
+        // tokens that cannot be adjacent, but the autofix inserts parens required for precedence, so there is no need for an extra space
+        invalid("+Math.pow(++a, b)", "+(++a**b)"),
+        invalid("Math.pow(a, b + c)in d", "a**(b + c)in d"),
+
+        // multiple invalid and full message and location test
+        {
+            code: "Math.pow(a, b) + Math.pow(c,\n d)",
+            output: "a**b + c**d",
+            errors: [
+                {
+                    message: "Use the '**' operator instead of 'Math.pow'.",
+                    type: "CallExpression",
+                    line: 1,
+                    column: 1,
+                    endLine: 1,
+                    endColumn: 15
+                },
+                {
+                    message: "Use the '**' operator instead of 'Math.pow'.",
+                    type: "CallExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 2,
+                    endColumn: 4
+                }
+            ]
+        },
+        {
+            code: "Math.pow(Math.pow(a, b), Math.pow(c, d))",
+            output: "Math.pow(a, b)**Math.pow(c, d)", // tests perform only one autofix iteration, below is the following one
+            errors: [
+                {
+                    messageId: "useExponentiation",
+                    type: "CallExpression",
+                    column: 1,
+                    endColumn: 41
+                },
+                {
+                    messageId: "useExponentiation",
+                    type: "CallExpression",
+                    column: 10,
+                    endColumn: 24
+                },
+                {
+                    messageId: "useExponentiation",
+                    type: "CallExpression",
+                    column: 26,
+                    endColumn: 40
+                }
+            ]
+        },
+        {
+            code: "Math.pow(a, b)**Math.pow(c, d)",
+            output: "(a**b)**c**d",
+            errors: [
+                {
+                    messageId: "useExponentiation",
+                    type: "CallExpression",
+                    column: 1,
+                    endColumn: 15
+                },
+                {
+                    messageId: "useExponentiation",
+                    type: "CallExpression",
+                    column: 17,
+                    endColumn: 31
+                }
+            ]
+        },
+
+        // shouldn't autofix if the call doesn't have exactly two arguments
+        invalid("Math.pow()", null),
+        invalid("Math.pow(a)", null),
+        invalid("Math.pow(a, b, c)", null),
+        invalid("Math.pow(a, b, c, d)", null),
+
+        // shouldn't autofix if any of the arguments is spread
+        invalid("Math.pow(...a)", null),
+        invalid("Math.pow(...a, b)", null),
+        invalid("Math.pow(a, ...b)", null),
+        invalid("Math.pow(a, b, ...c)", null),
+
+        // shouldn't autofix if that would remove comments
+        invalid("/* comment */Math.pow(a, b)", "/* comment */a**b"),
+        invalid("Math/**/.pow(a, b)", null),
+        invalid("Math//\n.pow(a, b)", null),
+        invalid("Math[//\n'pow'](a, b)", null),
+        invalid("Math['pow'/**/](a, b)", null),
+        invalid("Math./**/pow(a, b)", null),
+        invalid("Math.pow/**/(a, b)", null),
+        invalid("Math.pow//\n(a, b)", null),
+        invalid("Math.pow(/**/a, b)", null),
+        invalid("Math.pow(a,//\n b)", null),
+        invalid("Math.pow(a, b/**/)", null),
+        invalid("Math.pow(a, b//\n)", null),
+        invalid("Math.pow(a, b)/* comment */;", "a**b/* comment */;"),
+        invalid("Math.pow(a, b)// comment\n;", "a**b// comment\n;")
+    ]
+});
diff --git a/tests/lib/rules/space-infix-ops.js b/tests/lib/rules/space-infix-ops.js
index 85d61d449..590674345 100644
--- a/tests/lib/rules/space-infix-ops.js
+++ b/tests/lib/rules/space-infix-ops.js
@@ -57,7 +57,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '+' must be spaced.",
                 type: "BinaryExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 3
             }]
         },
         {
@@ -67,7 +68,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '+' must be spaced.",
                 type: "BinaryExpression",
                 line: 1,
-                column: 3
+                column: 3,
+                endColumn: 4
             }]
         },
         {
@@ -77,7 +79,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '+' must be spaced.",
                 type: "BinaryExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 3
             }]
         },
         {
@@ -87,7 +90,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '||' must be spaced.",
                 type: "LogicalExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 4
             }]
         },
         {
@@ -97,7 +101,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '||' must be spaced.",
                 type: "LogicalExpression",
                 line: 1,
-                column: 3
+                column: 3,
+                endColumn: 5
             }]
         },
         {
@@ -107,7 +112,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '||' must be spaced.",
                 type: "LogicalExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 4
             }]
         },
         {
@@ -147,7 +153,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '?' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 3
             }]
         },
         {
@@ -157,7 +164,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '?' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 3
             }]
         },
         {
@@ -167,7 +175,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator ':' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 6
+                column: 6,
+                endColumn: 7
             }]
         },
         {
@@ -177,7 +186,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '?' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 2
+                column: 2,
+                endColumn: 3
             }]
         },
         {
@@ -187,7 +197,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator '?' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 3
+                column: 3,
+                endColumn: 4
             }]
         },
         {
@@ -197,7 +208,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator ':' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 6
+                column: 6,
+                endColumn: 7
             }]
         },
         {
@@ -207,7 +219,8 @@ ruleTester.run("space-infix-ops", rule, {
                 message: "Operator ':' must be spaced.",
                 type: "ConditionalExpression",
                 line: 1,
-                column: 7
+                column: 7,
+                endColumn: 8
             }]
         },
         {
diff --git a/tests/lib/rules/use-isnan.js b/tests/lib/rules/use-isnan.js
index 82bad95cb..e494fc014 100644
--- a/tests/lib/rules/use-isnan.js
+++ b/tests/lib/rules/use-isnan.js
@@ -114,6 +114,102 @@ ruleTester.run("use-isnan", rule, {
         {
             code: "switch(foo) { case bar: break; case 1: break; default: break; }",
             options: [{ enforceForSwitchCase: true }]
+        },
+
+        //------------------------------------------------------------------------------
+        // enforceForIndexOf
+        //------------------------------------------------------------------------------
+
+        "foo.indexOf(NaN)",
+        "foo.lastIndexOf(NaN)",
+        {
+            code: "foo.indexOf(NaN)",
+            options: [{}]
+        },
+        {
+            code: "foo.lastIndexOf(NaN)",
+            options: [{}]
+        },
+        {
+            code: "foo.indexOf(NaN)",
+            options: [{ enforceForIndexOf: false }]
+        },
+        {
+            code: "foo.lastIndexOf(NaN)",
+            options: [{ enforceForIndexOf: false }]
+        },
+        {
+            code: "indexOf(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "lastIndexOf(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "new foo.indexOf(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.bar(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.IndexOf(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo[indexOf](NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo[lastIndexOf](NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "indexOf.foo(NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.indexOf()",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.lastIndexOf()",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.indexOf(a)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.lastIndexOf(Nan)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.indexOf(a, NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.lastIndexOf(NaN, b)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.indexOf(a, b)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.lastIndexOf(NaN, NaN)",
+            options: [{ enforceForIndexOf: true }]
+        },
+        {
+            code: "foo.indexOf(...NaN)",
+            options: [{ enforceForIndexOf: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "foo.lastIndexOf(NaN())",
+            options: [{ enforceForIndexOf: true }]
         }
     ],
     invalid: [
@@ -246,6 +342,41 @@ ruleTester.run("use-isnan", rule, {
                 { messageId: "switchNaN", type: "SwitchStatement", column: 1 },
                 { messageId: "caseNaN", type: "SwitchCase", column: 15 }
             ]
+        },
+
+        //------------------------------------------------------------------------------
+        // enforceForIndexOf
+        //------------------------------------------------------------------------------
+
+        {
+            code: "foo.indexOf(NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "indexOf" } }]
+        },
+        {
+            code: "foo.lastIndexOf(NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "lastIndexOf" } }]
+        },
+        {
+            code: "foo['indexOf'](NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "indexOf" } }]
+        },
+        {
+            code: "foo['lastIndexOf'](NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "lastIndexOf" } }]
+        },
+        {
+            code: "foo().indexOf(NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "indexOf" } }]
+        },
+        {
+            code: "foo.bar.lastIndexOf(NaN)",
+            options: [{ enforceForIndexOf: true }],
+            errors: [{ messageId: "indexOfNaN", type: "CallExpression", data: { methodName: "lastIndexOf" } }]
         }
     ]
 });