Repository: eslint/eslint
Pull request #12062 (2019-08-05 05:16:31)

Update: Fix accessor-pairs to enforce pairs per property in literals
<!--
    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 is a **bug fix**, not an enhancement, but it will produce more errors by default.

<!--
    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.1.0
* **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.**

```js
/*eslint accessor-pairs: "error"*/

var o = { get a() {}, set b(foo) {} };
```

**What did you expect to happen?**

By default, this rule reports setters without getters.

I would expect 1 error for the `b` setter.

**What actually happened? Please include the actual, raw output from ESLint.**

No warnings. 

The rule doesn't read property names in object literals. An object literal with a getter and a setter that are unrelated to each other is never reported, regardless of the settings.

<!--
    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)**

Fixed the logic for object literals.

**Is there anything you'd like reviewers to focus on?**

* The code which handles property descriptors is also changed (it had to be, because the same code was handling both property descriptors and 'usual' object literals), but the logic isn't. This code could also use `astUtils.getStaticPropertyName()` but I didn't change this as it would be an enhancement, not just a bug fix. I can do this in another PR, and there should be also more test cases for property descriptors (e.g. there are no test cases for getters without setters).
* In the new code which handles object literals, computed property keys that cannot be statically resolved to a `string` are compared by their tokens. This could be seen as an enhancement, but the rule didn't compare names anyway. This allows the rule to report cases like `{ set [a]() {} }`.
* The code is organized in a way that an option to check classes can be easily added, I'll open another issue for this option.
* There is one edge case which isn't handled (needs ES2015+ syntax enabled):

```js
var obj = {
  get a() {},
  a: 1,
  set a() {}
}
```

This is interpreted as 3 unrelated attempts to create the same key, the last wins and creates a setter without getter. I guess this isn't so important as the `no-dupe-keys` will report this literal.

As a side note, this could also happen in cases like this:

```js
var obj = {
  get a() {},
  ...anotherObj,
  set a() {}
}
```

perhaps it would be good to have a rule like `no-loose-accessors` (I'd be glad to implement it)







Patch:
diff --git a/README.md b/README.md
index ed485f66b..061eafefc 100644
--- a/README.md
+++ b/README.md
@@ -59,8 +59,6 @@ After that, you can run ESLint on any file or directory like this:
 $ ./node_modules/.bin/eslint yourfile.js
 ```
 
-It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, any plugins or shareable configs that you use must be installed locally in either case.
-
 ## <a name="configuration"></a>Configuration
 
 After running `eslint --init`, you'll have a `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
@@ -260,7 +258,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://salesforce.com"><img src="https://images.opencollective.com/salesforce/853ecef/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/001a341/logo.png" alt="Airbnb" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/fbopensource/fbb8a5b/logo.png" alt="Facebook Open Source" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ux-top-5/cae5dfe/logo.png" alt="UX Top 5" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/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> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/534b832/logo.png" alt="Faithlife" height="32"></a></p>
+<p><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://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/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> <a href="https://faithlife.com/ref/about"><img src="https://images.opencollective.com/faithlife/534b832/logo.png" alt="Faithlife" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/scope-manager-interface.md b/docs/developer-guide/scope-manager-interface.md
index 08986caa2..3ee5b23d3 100644
--- a/docs/developer-guide/scope-manager-interface.md
+++ b/docs/developer-guide/scope-manager-interface.md
@@ -28,7 +28,7 @@ This document was written based on the implementation of [eslint-scope](https://
     * `node` (`ASTNode`) ... An AST node to get their scope.
     * `inner` (`boolean`) ... If the node has multiple scope, this returns the outermost scope normally. If `inner` is `true` then this returns the innermost scope. Default is `false`.
 * **Return type:** `Scope | null`
-* **Description:** Get the scope of a given AST node. The gotten scope's `block` property is the node. This method never returns `function-expression-name` scope and `TDZ` scope. If the node does not have their scope, this returns `null`.
+* **Description:** Get the scope of a given AST node. The gotten scope's `block` property is the node. This method never returns `function-expression-name` scope. If the node does not have their scope, this returns `null`.
 
 #### getDeclaredVariables(node)
 
@@ -77,7 +77,7 @@ Those members are defined but not used in ESLint.
 #### type
 
 * **Type:** `string`
-* **Description:** The type of this scope. This is one of `"block"`, `"catch"`, `"class"`, `"for"`, `"function"`, `"function-expression-name"`, `"global"`, `"module"`, `"switch"`, `"with"`, `"TDZ"`
+* **Description:** The type of this scope. This is one of `"block"`, `"catch"`, `"class"`, `"for"`, `"function"`, `"function-expression-name"`, `"global"`, `"module"`, `"switch"`, `"with"`
 
 #### isStrict
 
@@ -334,7 +334,7 @@ Those members are defined but not used in ESLint.
 #### type
 
 * **Type:** `string`
-* **Description:** The type of this definition. One of `"CatchClause"`, `"ClassName"`, `"FunctionName"`, `"ImplicitGlobalVariable"`, `"ImportBinding"`, `"Parameter"`, `"TDZ"`, and `"Variable"`.
+* **Description:** The type of this definition. One of `"CatchClause"`, `"ClassName"`, `"FunctionName"`, `"ImplicitGlobalVariable"`, `"ImportBinding"`, `"Parameter"`, and `"Variable"`.
 
 #### name
 
@@ -354,7 +354,6 @@ Those members are defined but not used in ESLint.
 | `"ImplicitGlobalVariable"` | `Program`
 | `"ImportBinding"`          | `ImportSpecifier`, `ImportDefaultSpecifier`, or `ImportNamespaceSpecifier`
 | `"Parameter"`              | `FunctionDeclaration`, `FunctionExpression`, or `ArrowFunctionExpression`
-| `"TDZ"`                    | ?
 | `"Variable"`               | `VariableDeclarator`
 
 #### parent
@@ -370,7 +369,6 @@ Those members are defined but not used in ESLint.
 | `"ImplicitGlobalVariable"` | `null`
 | `"ImportBinding"`          | `ImportDeclaration`
 | `"Parameter"`              | `null`
-| `"TDZ"`                    | `null`
 | `"Variable"`               | `VariableDeclaration`
 
 ### Deprecated members
diff --git a/docs/rules/accessor-pairs.md b/docs/rules/accessor-pairs.md
index 1cbf7c9ef..207eedeac 100644
--- a/docs/rules/accessor-pairs.md
+++ b/docs/rules/accessor-pairs.md
@@ -143,6 +143,27 @@ Object.defineProperty(o, 'c', {
 
 ```
 
+## Known Limitations
+
+Due to the limits of static analysis, this rule does not account for possible side effects and in certain cases
+might not report a missing pair for a getter/setter that has a computed key, like in the following example:
+
+```js
+/*eslint accessor-pairs: "error"*/
+
+var a = 1;
+
+// no warnings
+var o = {
+    get [a++]() {
+        return this.val;
+    },
+    set [a++](value) {
+        this.val = value;
+    }
+};
+```
+
 ## When Not To Use It
 
 You can turn this rule off if you are not concerned with the simultaneous presence of setters and getters on objects.
diff --git a/docs/rules/function-call-argument-newline.md b/docs/rules/function-call-argument-newline.md
new file mode 100644
index 000000000..bdb98807f
--- /dev/null
+++ b/docs/rules/function-call-argument-newline.md
@@ -0,0 +1,202 @@
+# enforce line breaks between arguments of a function call (function-call-argument-newline)
+
+A number of style guides require or disallow line breaks between arguments of a function call.
+
+## Rule Details
+
+This rule enforces line breaks between arguments of a function call.
+
+## Options
+
+This rule has a string option:
+
+* `"always"` (default) requires line breaks between arguments
+* `"never"` disallows line breaks between arguments
+* `"consistent"` requires consistent usage of line breaks between arguments
+
+
+### always
+
+Examples of **incorrect** code for this rule with the default `"always"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "always"]*/
+
+foo("one", "two", "three");
+
+bar("one", "two", {
+    one: 1,
+    two: 2
+});
+
+baz("one", "two", (x) => {
+    console.log(x);
+});
+```
+
+Examples of **correct** code for this rule with the default `"always"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "always"]*/
+
+foo(
+    "one",
+    "two",
+    "three"
+);
+
+bar(
+    "one",
+    "two",
+    { one: 1, two: 2 }
+);
+// or
+bar(
+    "one",
+    "two",
+    {
+        one: 1,
+        two: 2
+    }
+);
+
+baz(
+    "one",
+    "two",
+    (x) => {
+        console.log(x);
+    }
+);
+```
+
+
+### never
+
+Examples of **incorrect** code for this rule with the default `"never"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "never"]*/
+
+foo(
+    "one",
+    "two", "three"
+);
+
+bar(
+    "one",
+    "two", {
+        one: 1,
+        two: 2
+    }
+);
+
+baz(
+    "one",
+    "two", (x) => {
+        console.log(x);
+    }
+);
+```
+
+Examples of **correct** code for this rule with the `"never"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "never"]*/
+
+foo("one", "two", "three");
+// or
+foo(
+    "one", "two", "three"
+);
+
+bar("one", "two", { one: 1, two: 2 });
+// or
+bar("one", "two", {
+    one: 1,
+    two: 2
+});
+
+baz("one", "two", (x) => {
+    console.log(x);
+});
+```
+
+### consistent
+
+Examples of **incorrect** code for this rule with the default `"consistent"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "consistent"]*/
+
+foo("one", "two",
+    "three");
+//or
+foo("one",
+    "two", "three");
+
+bar("one", "two",
+    { one: 1, two: 2}
+);
+
+baz("one", "two",
+    (x) => { console.log(x); }
+);
+```
+
+Examples of **correct** code for this rule with the default `"consistent"` option:
+
+```js
+/*eslint function-call-argument-newline: ["error", "consistent"]*/
+
+foo("one", "two", "three");
+// or
+foo(
+    "one",
+    "two",
+    "three"
+);
+
+bar("one", "two", {
+    one: 1,
+    two: 2
+});
+// or
+bar(
+    "one",
+    "two",
+    { one: 1, two: 2 }
+);
+// or
+bar(
+    "one",
+    "two",
+    {
+        one: 1,
+        two: 2
+    }
+);
+
+baz("one", "two", (x) => {
+    console.log(x);
+});
+// or
+baz(
+    "one",
+    "two",
+    (x) => {
+        console.log(x);
+    }
+);
+```
+
+
+## When Not To Use It
+
+If you don't want to enforce line breaks between arguments, don't enable this rule.
+
+## Related Rules
+
+* [function-paren-newline](function-paren-newline.md)
+* [func-call-spacing](func-call-spacing.md)
+* [object-property-newline](object-property-newline.md)
+* [array-element-newline](array-element-newline.md)
diff --git a/docs/rules/no-mixed-operators.md b/docs/rules/no-mixed-operators.md
index 3c0bb2fab..3206d18fb 100644
--- a/docs/rules/no-mixed-operators.md
+++ b/docs/rules/no-mixed-operators.md
@@ -5,6 +5,8 @@ This rule warns when different operators are used consecutively without parenthe
 
 ```js
 var foo = a && b || c || d;    /*BAD: Unexpected mix of '&&' and '||'.*/
+var foo = a && b ? c : d;      /*BAD: Unexpected mix of '&&' and '?:'.*/
+var foo = (a && b) ? c : d;    /*GOOD*/
 var foo = (a && b) || c || d;  /*GOOD*/
 var foo = a && (b || c || d);  /*GOOD*/
 ```
@@ -23,10 +25,21 @@ will generate
 1:18  Unexpected mix of '&&' and '||'. (no-mixed-operators)
 ```
 
+```js
+var foo = a && b ? c : d;
+```
+
+will generate
+
+```sh
+1:13  Unexpected mix of '&&' and '?:'. (no-mixed-operators)
+1:18  Unexpected mix of '&&' and '?:'. (no-mixed-operators)
+```
+
 
 ## Rule Details
 
-This rule checks `BinaryExpression` and `LogicalExpression`.
+This rule checks `BinaryExpression`, `LogicalExpression` and `ConditionalExpression`.
 
 This rule may conflict with [no-extra-parens](no-extra-parens.md) rule.
 If you use both this and [no-extra-parens](no-extra-parens.md) rule together, you need to use the `nestedBinaryExpressions` option of [no-extra-parens](no-extra-parens.md) rule.
@@ -75,7 +88,8 @@ var foo = (a + b) * c;
 
 This rule has 2 options.
 
-* `groups` (`string[][]`) - specifies operator groups to be checked. The `groups` option is a list of groups, and a group is a list of binary operators. Default operator groups are defined as arithmetic, bitwise, comparison, logical, and relational operators.
+* `groups` (`string[][]`) - specifies operator groups to be checked. The `groups` option is a list of groups, and a group is a list of binary operators. Default operator groups are defined as arithmetic, bitwise, comparison, logical, and relational operators. Note: Ternary operator(?:) can be part of any group and by default is allowed to be mixed with other operators.
+
 * `allowSamePrecedence` (`boolean`) - specifies whether to allow mixed operators if they are of equal precedence. Default is `true`.
 
 ### groups
@@ -87,6 +101,7 @@ The following operators can be used in `groups` option:
 * Comparison Operators: `"=="`, `"!="`, `"==="`, `"!=="`, `">"`, `">="`, `"<"`, `"<="`
 * Logical Operators: `"&&"`, `"||"`
 * Relational Operators: `"in"`, `"instanceof"`
+* Ternary Operator: `?:`
 
 Now, consider the following group configuration: `{"groups": [["&", "|", "^", "~", "<<", ">>", ">>>"], ["&&", "||"]]}`.
 There are 2 groups specified in this configuration: bitwise operators and logical operators.
@@ -102,6 +117,12 @@ var foo = a && b < 0 || c > 0 || d + 1 === 0;
 var foo = a & b | c;
 ```
 
+```js
+/*eslint no-mixed-operators: ["error", {"groups": [["&&", "||", "?:"]]}]*/
+
+var foo = a || b ? c : d;
+```
+
 Examples of **correct** code for this rule with `{"groups": [["&", "|", "^", "~", "<<", ">>", ">>>"], ["&&", "||"]]}` option:
 
 ```js
@@ -118,6 +139,13 @@ var foo = a + (b * c);
 var foo = (a + b) * c;
 ```
 
+```js
+/*eslint no-mixed-operators: ["error", {"groups": [["&&", "||", "?:"]]}]*/
+
+var foo = (a || b) ? c : d;
+var foo = a || (b ? c : d);
+```
+
 ### allowSamePrecedence
 
 Examples of **correct** code for this rule with `{"allowSamePrecedence": true}` option:
diff --git a/docs/rules/no-undef.md b/docs/rules/no-undef.md
index f5dc5a280..faaf978cc 100644
--- a/docs/rules/no-undef.md
+++ b/docs/rules/no-undef.md
@@ -11,32 +11,25 @@ Examples of **incorrect** code for this rule:
 ```js
 /*eslint no-undef: "error"*/
 
-var a = someFunction();
-b = 10;
+var foo = someFunction();
+var bar = a + 1;
 ```
 
 Examples of **correct** code for this rule with `global` declaration:
 
 ```js
-/*global someFunction b:writable*/
+/*global someFunction, a*/
 /*eslint no-undef: "error"*/
 
-var a = someFunction();
-b = 10;
+var foo = someFunction();
+var bar = a + 1;
 ```
 
-The `b:writable` syntax in `/*global */` indicates that assignment to `b` is correct.
+Note that this rule does not disallow assignments to read-only global variables.
+See [no-global-assign](no-global-assign.md) if you also want to disallow those assignments.
 
-Examples of **incorrect** code for this rule with `global` declaration:
-
-```js
-/*global b*/
-/*eslint no-undef: "error"*/
-
-b = 10;
-```
-
-By default, variables declared in `/*global */` are read-only, therefore assignment is incorrect.
+This rule also does not disallow redeclarations of global variables.
+See [no-redeclare](no-redeclare.md) if you also want to disallow those redeclarations.
 
 ## Options
 
@@ -111,3 +104,8 @@ If explicit declaration of global variables is not to your taste.
 ## Compatibility
 
 This rule provides compatibility with treatment of global variables in [JSHint](http://jshint.com/) and [JSLint](http://www.jslint.com).
+
+## Related Rules
+
+* [no-global-assign](no-global-assign.md)
+* [no-redeclare](no-redeclare.md)
diff --git a/docs/user-guide/getting-started.md b/docs/user-guide/getting-started.md
index 45633f618..1bebf7d69 100644
--- a/docs/user-guide/getting-started.md
+++ b/docs/user-guide/getting-started.md
@@ -33,7 +33,7 @@ After that, you can run ESLint on any file or directory like this:
 $ ./node_modules/.bin/eslint yourfile.js
 ```
 
-It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, any plugins or shareable configs that you use must be installed locally in either case.
+It is also possible to install ESLint globally rather than locally (using `npm install eslint --global`). However, this is not recommended, and any plugins or shareable configs that you use must be installed locally in either case.
 
 ## Configuration
 
diff --git a/lib/init/npm-utils.js b/lib/init/npm-utils.js
index 26e78406f..3a680aae9 100644
--- a/lib/init/npm-utils.js
+++ b/lib/init/npm-utils.js
@@ -135,7 +135,7 @@ function check(packages, opt) {
  * Check whether node modules are included in the dependencies of a project's
  * package.json.
  *
- * Convienience wrapper around check().
+ * Convenience wrapper around check().
  *
  * @param   {string[]} packages  Array of node modules to check.
  * @param   {string}   rootDir   The directory contianing a package.json
@@ -150,7 +150,7 @@ function checkDeps(packages, rootDir) {
  * Check whether node modules are included in the devDependencies of a project's
  * package.json.
  *
- * Convienience wrapper around check().
+ * Convenience wrapper around check().
  *
  * @param   {string[]} packages  Array of node modules to check.
  * @returns {Object}             An object whose keys are the module names
diff --git a/lib/rules/accessor-pairs.js b/lib/rules/accessor-pairs.js
index aca231848..9c78bdc70 100644
--- a/lib/rules/accessor-pairs.js
+++ b/lib/rules/accessor-pairs.js
@@ -5,10 +5,87 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/**
+ * Property name if it can be computed statically, otherwise the list of the tokens of the key node.
+ * @typedef {string|Token[]} Key
+ */
+
+/**
+ * Accessor nodes with the same key.
+ * @typedef {Object} AccessorData
+ * @property {Key} key Accessor's key
+ * @property {ASTNode[]} getters List of getter nodes.
+ * @property {ASTNode[]} setters List of setter nodes.
+ */
+
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
 
+/**
+ * Checks whether or not the given lists represent the equal tokens in the same order.
+ * Tokens are compared by their properties, not by instance.
+ * @param {Token[]} left First list of tokens.
+ * @param {Token[]} right Second list of tokens.
+ * @returns {boolean} `true` if the lists have same tokens.
+ */
+function areEqualTokenLists(left, right) {
+    if (left.length !== right.length) {
+        return false;
+    }
+
+    for (let i = 0; i < left.length; i++) {
+        const leftToken = left[i],
+            rightToken = right[i];
+
+        if (leftToken.type !== rightToken.type || leftToken.value !== rightToken.value) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+/**
+ * Checks whether or not the given keys are equal.
+ * @param {Key} left First key.
+ * @param {Key} right Second key.
+ * @returns {boolean} `true` if the keys are equal.
+ */
+function areEqualKeys(left, right) {
+    if (typeof left === "string" && typeof right === "string") {
+
+        // Statically computed names.
+        return left === right;
+    }
+    if (Array.isArray(left) && Array.isArray(right)) {
+
+        // Token lists.
+        return areEqualTokenLists(left, right);
+    }
+
+    return false;
+}
+
+/**
+ * Checks whether or not a given node is of an accessor kind ('get' or 'set').
+ * @param {ASTNode} node - A node to check.
+ * @returns {boolean} `true` if the node is of an accessor kind.
+ */
+function isAccessorKind(node) {
+    return node.kind === "get" || node.kind === "set";
+}
+
 /**
  * Checks whether or not a given node is an `Identifier` node which was named a given name.
  * @param {ASTNode} node - A node to check.
@@ -97,69 +174,152 @@ module.exports = {
         }],
 
         messages: {
-            getter: "Getter is not present.",
-            setter: "Setter is not present."
+            missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.",
+            missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.",
+            missingGetterInObjectLiteral: "Getter is not present for {{ name }}.",
+            missingSetterInObjectLiteral: "Setter is not present for {{ name }}."
         }
     },
     create(context) {
         const config = context.options[0] || {};
         const checkGetWithoutSet = config.getWithoutSet === true;
         const checkSetWithoutGet = config.setWithoutGet !== false;
+        const sourceCode = context.getSourceCode();
 
         /**
-         * Checks a object expression to see if it has setter and getter both present or none.
-         * @param {ASTNode} node The node to check.
+         * Reports the given node.
+         * @param {ASTNode} node The node to report.
+         * @param {string} messageKind "missingGetter" or "missingSetter".
          * @returns {void}
          * @private
          */
-        function checkLonelySetGet(node) {
-            let isSetPresent = false;
-            let isGetPresent = false;
-            const isDescriptor = isPropertyDescriptor(node);
+        function report(node, messageKind) {
+            if (node.type === "Property") {
+                context.report({
+                    node,
+                    messageId: `${messageKind}InObjectLiteral`,
+                    loc: astUtils.getFunctionHeadLoc(node.value, sourceCode),
+                    data: { name: astUtils.getFunctionNameWithKind(node.value) }
+                });
+            } else {
+                context.report({
+                    node,
+                    messageId: `${messageKind}InPropertyDescriptor`
+                });
+            }
+        }
 
-            for (let i = 0, end = node.properties.length; i < end; i++) {
-                const property = node.properties[i];
+        /**
+         * Reports each of the nodes in the given list using the same messageId.
+         * @param {ASTNode[]} nodes Nodes to report.
+         * @param {string} messageKind "missingGetter" or "missingSetter".
+         * @returns {void}
+         * @private
+         */
+        function reportList(nodes, messageKind) {
+            for (const node of nodes) {
+                report(node, messageKind);
+            }
+        }
 
-                let propToCheck = "";
+        /**
+         * Creates a new `AccessorData` object for the given getter or setter node.
+         * @param {ASTNode} node A getter or setter node.
+         * @returns {AccessorData} New `AccessorData` object that contains the given node.
+         * @private
+         */
+        function createAccessorData(node) {
+            const name = astUtils.getStaticPropertyName(node);
+            const key = (name !== null) ? name : sourceCode.getTokens(node.key);
 
-                if (property.kind === "init") {
-                    if (isDescriptor && !property.computed) {
-                        propToCheck = property.key.name;
-                    }
-                } else {
-                    propToCheck = property.kind;
-                }
+            return {
+                key,
+                getters: node.kind === "get" ? [node] : [],
+                setters: node.kind === "set" ? [node] : []
+            };
+        }
 
-                switch (propToCheck) {
-                    case "set":
-                        isSetPresent = true;
-                        break;
+        /**
+         * Merges the given `AccessorData` object into the given accessors list.
+         * @param {AccessorData[]} accessors The list to merge into.
+         * @param {AccessorData} accessorData The object to merge.
+         * @returns {AccessorData[]} The same instance with the merged object.
+         * @private
+         */
+        function mergeAccessorData(accessors, accessorData) {
+            const equalKeyElement = accessors.find(a => areEqualKeys(a.key, accessorData.key));
 
-                    case "get":
-                        isGetPresent = true;
-                        break;
+            if (equalKeyElement) {
+                equalKeyElement.getters.push(...accessorData.getters);
+                equalKeyElement.setters.push(...accessorData.setters);
+            } else {
+                accessors.push(accessorData);
+            }
 
-                    default:
+            return accessors;
+        }
 
-                        // Do nothing
-                }
+        /**
+         * Checks accessor pairs in the given list of nodes.
+         * @param {ASTNode[]} nodes The list to check.
+         * @returns {void}
+         * @private
+         */
+        function checkList(nodes) {
+            const accessors = nodes
+                .filter(isAccessorKind)
+                .map(createAccessorData)
+                .reduce(mergeAccessorData, []);
 
-                if (isSetPresent && isGetPresent) {
-                    break;
+            for (const { getters, setters } of accessors) {
+                if (checkSetWithoutGet && setters.length && !getters.length) {
+                    reportList(setters, "missingGetter");
+                }
+                if (checkGetWithoutSet && getters.length && !setters.length) {
+                    reportList(getters, "missingSetter");
                 }
             }
+        }
 
-            if (checkSetWithoutGet && isSetPresent && !isGetPresent) {
-                context.report({ node, messageId: "getter" });
-            } else if (checkGetWithoutSet && isGetPresent && !isSetPresent) {
-                context.report({ node, messageId: "setter" });
+        /**
+         * Checks accessor pairs in an object literal.
+         * @param {ASTNode} node `ObjectExpression` node to check.
+         * @returns {void}
+         * @private
+         */
+        function checkObjectLiteral(node) {
+            checkList(node.properties.filter(p => p.type === "Property"));
+        }
+
+        /**
+         * Checks accessor pairs in a property descriptor.
+         * @param {ASTNode} node Property descriptor `ObjectExpression` node to check.
+         * @returns {void}
+         * @private
+         */
+        function checkPropertyDescriptor(node) {
+            const namesToCheck = node.properties
+                .filter(p => p.type === "Property" && p.kind === "init" && !p.computed)
+                .map(({ key }) => key.name);
+
+            const hasGetter = namesToCheck.includes("get");
+            const hasSetter = namesToCheck.includes("set");
+
+            if (checkSetWithoutGet && hasSetter && !hasGetter) {
+                report(node, "missingGetter");
+            }
+            if (checkGetWithoutSet && hasGetter && !hasSetter) {
+                report(node, "missingSetter");
             }
         }
 
         return {
             ObjectExpression(node) {
                 if (checkSetWithoutGet || checkGetWithoutSet) {
-                    checkLonelySetGet(node);
+                    checkObjectLiteral(node);
+                    if (isPropertyDescriptor(node)) {
+                        checkPropertyDescriptor(node);
+                    }
                 }
             }
         };
diff --git a/lib/rules/class-methods-use-this.js b/lib/rules/class-methods-use-this.js
index 0eb1da87f..4bf17090a 100644
--- a/lib/rules/class-methods-use-this.js
+++ b/lib/rules/class-methods-use-this.js
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -34,7 +40,7 @@ module.exports = {
         }],
 
         messages: {
-            missingThis: "Expected 'this' to be used by class method '{{name}}'."
+            missingThis: "Expected 'this' to be used by class {{name}}."
         }
     },
     create(context) {
@@ -70,7 +76,8 @@ module.exports = {
          * @private
          */
         function isIncludedInstanceMethod(node) {
-            return isInstanceMethod(node) && !exceptMethods.has(node.key.name);
+            return isInstanceMethod(node) &&
+                (node.computed || !exceptMethods.has(node.key.name));
         }
 
         /**
@@ -89,7 +96,7 @@ module.exports = {
                     node,
                     messageId: "missingThis",
                     data: {
-                        name: node.parent.key.name
+                        name: astUtils.getFunctionNameWithKind(node)
                     }
                 });
             }
diff --git a/lib/rules/dot-notation.js b/lib/rules/dot-notation.js
index 61184ddcd..2e8fff8b9 100644
--- a/lib/rules/dot-notation.js
+++ b/lib/rules/dot-notation.js
@@ -9,13 +9,16 @@
 //------------------------------------------------------------------------------
 
 const astUtils = require("./utils/ast-utils");
+const keywords = require("./utils/keywords");
 
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
 const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
-const keywords = require("./utils/keywords");
+
+// `null` literal must be handled separately.
+const literalTypesToCheck = new Set(["string", "boolean"]);
 
 module.exports = {
     meta: {
@@ -115,7 +118,8 @@ module.exports = {
             MemberExpression(node) {
                 if (
                     node.computed &&
-                    node.property.type === "Literal"
+                    node.property.type === "Literal" &&
+                    (literalTypesToCheck.has(typeof node.property.value) || astUtils.isNullLiteral(node.property))
                 ) {
                     checkComputedProperty(node, node.property.value);
                 }
diff --git a/lib/rules/function-call-argument-newline.js b/lib/rules/function-call-argument-newline.js
new file mode 100644
index 000000000..8bf31f7c7
--- /dev/null
+++ b/lib/rules/function-call-argument-newline.js
@@ -0,0 +1,120 @@
+/**
+ * @fileoverview Rule to enforce line breaks between arguments of a function call
+ * @author Alexey Gonchar <https://github.com/finico>
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "layout",
+
+        docs: {
+            description: "enforce line breaks between arguments of a function call",
+            category: "Stylistic Issues",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/function-call-argument-newline"
+        },
+
+        fixable: "whitespace",
+
+        schema: [
+            {
+                enum: ["always", "never", "consistent"]
+            }
+        ],
+
+        messages: {
+            unexpectedLineBreak: "There should be no line break here.",
+            missingLineBreak: "There should be a line break after this argument."
+        }
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+
+        const checkers = {
+            unexpected: {
+                messageId: "unexpectedLineBreak",
+                check: (prevToken, currentToken) => prevToken.loc.start.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,
+                createFix: (token, tokenBefore) => fixer =>
+                    fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n")
+            }
+        };
+
+        /**
+         * Check all arguments for line breaks in the CallExpression
+         * @param {CallExpression} node node to evaluate
+         * @param {{ messageId: string, check: Function }} checker selected checker
+         * @returns {void}
+         * @private
+         */
+        function checkArguments(node, checker) {
+            for (let i = 1; i < node.arguments.length; i++) {
+                const prevArgToken = sourceCode.getFirstToken(node.arguments[i - 1]);
+                const currentArgToken = sourceCode.getFirstToken(node.arguments[i]);
+
+                if (checker.check(prevArgToken, currentArgToken)) {
+                    const tokenBefore = sourceCode.getTokenBefore(
+                        currentArgToken,
+                        { includeComments: true }
+                    );
+
+                    context.report({
+                        node,
+                        loc: {
+                            start: tokenBefore.loc.end,
+                            end: currentArgToken.loc.start
+                        },
+                        messageId: checker.messageId,
+                        fix: checker.createFix(currentArgToken, tokenBefore)
+                    });
+                }
+            }
+        }
+
+        /**
+         * Check if open space is present in a function name
+         * @param {CallExpression} node node to evaluate
+         * @returns {void}
+         * @private
+         */
+        function check(node) {
+            if (node.arguments.length < 2) {
+                return;
+            }
+
+            const option = context.options[0] || "always";
+
+            if (option === "never") {
+                checkArguments(node, checkers.unexpected);
+            } else if (option === "always") {
+                checkArguments(node, checkers.missing);
+            } else if (option === "consistent") {
+                const firstArgToken = sourceCode.getFirstToken(node.arguments[0]);
+                const secondArgToken = sourceCode.getFirstToken(node.arguments[1]);
+
+                if (firstArgToken.loc.start.line === secondArgToken.loc.start.line) {
+                    checkArguments(node, checkers.unexpected);
+                } else {
+                    checkArguments(node, checkers.missing);
+                }
+            }
+        }
+
+        return {
+            CallExpression: check,
+            NewExpression: check
+        };
+    }
+};
diff --git a/lib/rules/index.js b/lib/rules/index.js
index 45045904b..c42ae41d6 100644
--- a/lib/rules/index.js
+++ b/lib/rules/index.js
@@ -46,6 +46,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
     "func-name-matching": () => require("./func-name-matching"),
     "func-names": () => require("./func-names"),
     "func-style": () => require("./func-style"),
+    "function-call-argument-newline": () => require("./function-call-argument-newline"),
     "function-paren-newline": () => require("./function-paren-newline"),
     "generator-star-spacing": () => require("./generator-star-spacing"),
     "getter-return": () => require("./getter-return"),
diff --git a/lib/rules/no-dupe-keys.js b/lib/rules/no-dupe-keys.js
index d0751b4a2..1b7f69cfa 100644
--- a/lib/rules/no-dupe-keys.js
+++ b/lib/rules/no-dupe-keys.js
@@ -120,7 +120,7 @@ module.exports = {
                 }
 
                 // Skip if the name is not static.
-                if (!name) {
+                if (name === null) {
                     return;
                 }
 
diff --git a/lib/rules/no-duplicate-case.js b/lib/rules/no-duplicate-case.js
index 93c8548f9..c8a0fa9da 100644
--- a/lib/rules/no-duplicate-case.js
+++ b/lib/rules/no-duplicate-case.js
@@ -33,17 +33,19 @@ module.exports = {
 
         return {
             SwitchStatement(node) {
-                const mapping = {};
+                const previousKeys = new Set();
 
-                node.cases.forEach(switchCase => {
-                    const key = sourceCode.getText(switchCase.test);
+                for (const switchCase of node.cases) {
+                    if (switchCase.test) {
+                        const key = sourceCode.getText(switchCase.test);
 
-                    if (mapping[key]) {
-                        context.report({ node: switchCase, messageId: "unexpected" });
-                    } else {
-                        mapping[key] = switchCase;
+                        if (previousKeys.has(key)) {
+                            context.report({ node: switchCase, messageId: "unexpected" });
+                        } else {
+                            previousKeys.add(key);
+                        }
                     }
-                });
+                }
             }
         };
     }
diff --git a/lib/rules/no-extra-bind.js b/lib/rules/no-extra-bind.js
index 5380cf217..cc0b1f843 100644
--- a/lib/rules/no-extra-bind.js
+++ b/lib/rules/no-extra-bind.js
@@ -98,6 +98,7 @@ module.exports = {
                 grandparent.type === "CallExpression" &&
                 grandparent.callee === parent &&
                 grandparent.arguments.length === 1 &&
+                grandparent.arguments[0].type !== "SpreadElement" &&
                 parent.type === "MemberExpression" &&
                 parent.object === node &&
                 astUtils.getStaticPropertyName(parent) === "bind"
diff --git a/lib/rules/no-extra-boolean-cast.js b/lib/rules/no-extra-boolean-cast.js
index 8dd526477..9ae9b5be6 100644
--- a/lib/rules/no-extra-boolean-cast.js
+++ b/lib/rules/no-extra-boolean-cast.js
@@ -50,8 +50,8 @@ module.exports = {
         /**
          * Check if a node is in a context where its value would be coerced to a boolean at runtime.
          *
-         * @param {Object} node The node
-         * @param {Object} parent Its parent
+         * @param {ASTNode} node The node
+         * @param {ASTNode} parent Its parent
          * @returns {boolean} If it is in a boolean context
          */
         function isInBooleanContext(node, parent) {
@@ -65,6 +65,15 @@ module.exports = {
             );
         }
 
+        /**
+         * Check if a node has comments inside.
+         *
+         * @param {ASTNode} node The node to check.
+         * @returns {boolean} `true` if it has comments inside.
+         */
+        function hasCommentsInside(node) {
+            return Boolean(sourceCode.getCommentsInside(node).length);
+        }
 
         return {
             UnaryExpression(node) {
@@ -89,7 +98,12 @@ module.exports = {
                     context.report({
                         node,
                         messageId: "unexpectedNegation",
-                        fix: fixer => fixer.replaceText(parent, sourceCode.getText(node.argument))
+                        fix: fixer => {
+                            if (hasCommentsInside(parent)) {
+                                return null;
+                            }
+                            return fixer.replaceText(parent, sourceCode.getText(node.argument));
+                        }
                     });
                 }
             },
@@ -106,10 +120,35 @@ module.exports = {
                         messageId: "unexpectedCall",
                         fix: fixer => {
                             if (!node.arguments.length) {
-                                return fixer.replaceText(parent, "true");
+                                if (parent.type === "UnaryExpression" && parent.operator === "!") {
+
+                                    // !Boolean() -> true
+
+                                    if (hasCommentsInside(parent)) {
+                                        return null;
+                                    }
+
+                                    const replacement = "true";
+                                    let prefix = "";
+                                    const tokenBefore = sourceCode.getTokenBefore(parent);
+
+                                    if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
+                                            !astUtils.canTokensBeAdjacent(tokenBefore, replacement)) {
+                                        prefix = " ";
+                                    }
+
+                                    return fixer.replaceText(parent, prefix + replacement);
+                                }
+
+                                // Boolean() -> false
+                                if (hasCommentsInside(node)) {
+                                    return null;
+                                }
+                                return fixer.replaceText(node, "false");
                             }
 
-                            if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement") {
+                            if (node.arguments.length > 1 || node.arguments[0].type === "SpreadElement" ||
+                                    hasCommentsInside(node)) {
                                 return null;
                             }
 
diff --git a/lib/rules/no-extra-parens.js b/lib/rules/no-extra-parens.js
index c9278f2d0..5e41d7468 100644
--- a/lib/rules/no-extra-parens.js
+++ b/lib/rules/no-extra-parens.js
@@ -980,7 +980,21 @@ module.exports = {
 
             SpreadElement: checkSpreadOperator,
             SpreadProperty: checkSpreadOperator,
-            ExperimentalSpreadProperty: checkSpreadOperator
+            ExperimentalSpreadProperty: checkSpreadOperator,
+
+            TemplateLiteral(node) {
+                node.expressions
+                    .filter(e => e && hasExcessParens(e))
+                    .forEach(report);
+            },
+
+            AssignmentPattern(node) {
+                const { right } = node;
+
+                if (right && hasExcessParens(right) && precedence(right) >= PRECEDENCE_OF_ASSIGNMENT_EXPR) {
+                    report(right);
+                }
+            }
         };
 
     }
diff --git a/lib/rules/no-mixed-operators.js b/lib/rules/no-mixed-operators.js
index 21e1d95c6..8d1c7a6af 100644
--- a/lib/rules/no-mixed-operators.js
+++ b/lib/rules/no-mixed-operators.js
@@ -20,12 +20,14 @@ const BITWISE_OPERATORS = ["&", "|", "^", "~", "<<", ">>", ">>>"];
 const COMPARISON_OPERATORS = ["==", "!=", "===", "!==", ">", ">=", "<", "<="];
 const LOGICAL_OPERATORS = ["&&", "||"];
 const RELATIONAL_OPERATORS = ["in", "instanceof"];
+const TERNARY_OPERATOR = ["?:"];
 const ALL_OPERATORS = [].concat(
     ARITHMETIC_OPERATORS,
     BITWISE_OPERATORS,
     COMPARISON_OPERATORS,
     LOGICAL_OPERATORS,
-    RELATIONAL_OPERATORS
+    RELATIONAL_OPERATORS,
+    TERNARY_OPERATOR
 );
 const DEFAULT_GROUPS = [
     ARITHMETIC_OPERATORS,
@@ -34,7 +36,7 @@ const DEFAULT_GROUPS = [
     LOGICAL_OPERATORS,
     RELATIONAL_OPERATORS
 ];
-const TARGET_NODE_TYPE = /^(?:Binary|Logical)Expression$/u;
+const TARGET_NODE_TYPE = /^(?:Binary|Logical|Conditional)Expression$/u;
 
 /**
  * Normalizes options.
@@ -65,6 +67,18 @@ function includesBothInAGroup(groups, left, right) {
     return groups.some(group => group.indexOf(left) !== -1 && group.indexOf(right) !== -1);
 }
 
+/**
+ * Checks whether the given node is a conditional expression and returns the test node else the left node.
+ *
+ * @param {ASTNode} node - A node which can be a BinaryExpression or a LogicalExpression node.
+ * This parent node can be BinaryExpression, LogicalExpression
+ *      , or a ConditionalExpression node
+ * @returns {ASTNode} node the appropriate node(left or test).
+ */
+function getChildNode(node) {
+    return node.type === "ConditionalExpression" ? node.test : node.left;
+}
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -121,7 +135,7 @@ module.exports = {
             const b = node.parent;
 
             return (
-                !includesBothInAGroup(options.groups, a.operator, b.operator) ||
+                !includesBothInAGroup(options.groups, a.operator, b.type === "ConditionalExpression" ? "?:" : b.operator) ||
                 (
                     options.allowSamePrecedence &&
                     astUtils.getPrecedence(a) === astUtils.getPrecedence(b)
@@ -139,12 +153,25 @@ module.exports = {
          * @returns {boolean} `true` if the node was mixed.
          */
         function isMixedWithParent(node) {
+
             return (
                 node.operator !== node.parent.operator &&
                 !astUtils.isParenthesised(sourceCode, node)
             );
         }
 
+        /**
+         * Checks whether the operator of a given node is mixed with a
+         * conditional expression.
+         *
+         * @param {ASTNode} node - A node to check. This is a conditional
+         *      expression node
+         * @returns {boolean} `true` if the node was mixed.
+         */
+        function isMixedWithConditionalParent(node) {
+            return !astUtils.isParenthesised(sourceCode, node) && !astUtils.isParenthesised(sourceCode, node.test);
+        }
+
         /**
          * Gets the operator token of a given node.
          *
@@ -153,7 +180,7 @@ module.exports = {
          * @returns {Token} The operator token of the node.
          */
         function getOperatorToken(node) {
-            return sourceCode.getTokenAfter(node.left, astUtils.isNotClosingParenToken);
+            return sourceCode.getTokenAfter(getChildNode(node), astUtils.isNotClosingParenToken);
         }
 
         /**
@@ -167,13 +194,13 @@ module.exports = {
          */
         function reportBothOperators(node) {
             const parent = node.parent;
-            const left = (parent.left === node) ? node : parent;
-            const right = (parent.left !== node) ? node : parent;
+            const left = (getChildNode(parent) === node) ? node : parent;
+            const right = (getChildNode(parent) !== node) ? node : parent;
             const message =
                 "Unexpected mix of '{{leftOperator}}' and '{{rightOperator}}'.";
             const data = {
-                leftOperator: left.operator,
-                rightOperator: right.operator
+                leftOperator: left.operator || "?:",
+                rightOperator: right.operator || "?:"
             };
 
             context.report({
@@ -198,17 +225,25 @@ module.exports = {
          * @returns {void}
          */
         function check(node) {
-            if (TARGET_NODE_TYPE.test(node.parent.type) &&
-                isMixedWithParent(node) &&
-                !shouldIgnore(node)
-            ) {
-                reportBothOperators(node);
+            if (TARGET_NODE_TYPE.test(node.parent.type)) {
+                if (node.parent.type === "ConditionalExpression" && !shouldIgnore(node) && isMixedWithConditionalParent(node.parent)) {
+                    reportBothOperators(node);
+                } else {
+                    if (TARGET_NODE_TYPE.test(node.parent.type) &&
+                        isMixedWithParent(node) &&
+                        !shouldIgnore(node)
+                    ) {
+                        reportBothOperators(node);
+                    }
+                }
             }
+
         }
 
         return {
             BinaryExpression: check,
             LogicalExpression: check
+
         };
     }
 };
diff --git a/lib/rules/no-restricted-syntax.js b/lib/rules/no-restricted-syntax.js
index 74eea1478..41aa9fa39 100644
--- a/lib/rules/no-restricted-syntax.js
+++ b/lib/rules/no-restricted-syntax.js
@@ -21,7 +21,7 @@ module.exports = {
 
         schema: {
             type: "array",
-            items: [{
+            items: {
                 oneOf: [
                     {
                         type: "string"
@@ -36,7 +36,7 @@ module.exports = {
                         additionalProperties: false
                     }
                 ]
-            }],
+            },
             uniqueItems: true,
             minItems: 0
         }
diff --git a/lib/rules/no-unused-vars.js b/lib/rules/no-unused-vars.js
index 48df3aa3c..8094de57c 100644
--- a/lib/rules/no-unused-vars.js
+++ b/lib/rules/no-unused-vars.js
@@ -507,7 +507,7 @@ module.exports = {
             const childScopes = scope.childScopes;
             let i, l;
 
-            if (scope.type !== "TDZ" && (scope.type !== "global" || config.vars === "all")) {
+            if (scope.type !== "global" || config.vars === "all") {
                 for (i = 0, l = variables.length; i < l; ++i) {
                     const variable = variables[i];
 
diff --git a/lib/rules/prefer-template.js b/lib/rules/prefer-template.js
index f73ac34f8..a2507d452 100644
--- a/lib/rules/prefer-template.js
+++ b/lib/rules/prefer-template.js
@@ -52,16 +52,7 @@ function isOctalEscapeSequence(node) {
         return false;
     }
 
-    const match = node.raw.match(/^([^\\]|\\[^0-7])*\\([0-7]{1,3})/u);
-
-    if (match) {
-
-        // \0 is actually not considered an octal
-        if (match[2] !== "0" || typeof match[3] !== "undefined") {
-            return true;
-        }
-    }
-    return false;
+    return astUtils.hasOctalEscapeSequence(node.raw);
 }
 
 /**
diff --git a/lib/rules/sort-keys.js b/lib/rules/sort-keys.js
index beda42f1e..c314d4a63 100644
--- a/lib/rules/sort-keys.js
+++ b/lib/rules/sort-keys.js
@@ -29,7 +29,13 @@ const astUtils = require("./utils/ast-utils"),
  * @private
  */
 function getPropertyName(node) {
-    return astUtils.getStaticPropertyName(node) || node.key.name || null;
+    const staticName = astUtils.getStaticPropertyName(node);
+
+    if (staticName !== null) {
+        return staticName;
+    }
+
+    return node.key.name || null;
 }
 
 /**
@@ -151,9 +157,11 @@ module.exports = {
                 const numKeys = stack.numKeys;
                 const thisName = getPropertyName(node);
 
-                stack.prevName = thisName || prevName;
+                if (thisName !== null) {
+                    stack.prevName = thisName;
+                }
 
-                if (!prevName || !thisName || numKeys < minKeys) {
+                if (prevName === null || thisName === null || numKeys < minKeys) {
                     return;
                 }
 
diff --git a/lib/rules/utils/ast-utils.js b/lib/rules/utils/ast-utils.js
index 78ae7bc01..7c17fc2ec 100644
--- a/lib/rules/utils/ast-utils.js
+++ b/lib/rules/utils/ast-utils.js
@@ -38,6 +38,7 @@ const LINEBREAKS = new Set(["\r\n", "\r", "\n", "\u2028", "\u2029"]);
 const STATEMENT_LIST_PARENTS = new Set(["Program", "BlockStatement", "SwitchCase"]);
 
 const DECIMAL_INTEGER_PATTERN = /^(0|[1-9]\d*)$/u;
+const OCTAL_ESCAPE_PATTERN = /^(?:[^\\]|\\[^0-7]|\\0(?![0-9]))*\\(?:[1-7]|0[0-9])/u;
 
 /**
  * Checks reference if is non initializer and writable.
@@ -1101,7 +1102,7 @@ module.exports = {
         } else {
             const name = module.exports.getStaticPropertyName(parent);
 
-            if (name) {
+            if (name !== null) {
                 tokens.push(`'${name}'`);
             }
         }
@@ -1373,5 +1374,20 @@ module.exports = {
             "/*".length +
             (match ? match.index + 1 : 0)
         );
+    },
+
+    /**
+     * Determines whether the given raw string contains an octal escape sequence.
+     *
+     * "\1", "\2" ... "\7"
+     * "\00", "\01" ... "\09"
+     *
+     * "\0", when not followed by a digit, is not an octal escape sequence.
+     *
+     * @param {string} rawString A string in its raw representation.
+     * @returns {boolean} `true` if the string contains at least one octal escape sequence.
+     */
+    hasOctalEscapeSequence(rawString) {
+        return OCTAL_ESCAPE_PATTERN.test(rawString);
     }
 };
diff --git a/lib/rules/yoda.js b/lib/rules/yoda.js
index 43783c193..89c4a8afd 100644
--- a/lib/rules/yoda.js
+++ b/lib/rules/yoda.js
@@ -119,7 +119,7 @@ function same(a, b) {
             const nameA = astUtils.getStaticPropertyName(a);
 
             // x.y = x["y"]
-            if (nameA) {
+            if (nameA !== null) {
                 return (
                     same(a.object, b.object) &&
                     nameA === astUtils.getStaticPropertyName(b)
diff --git a/tools/rule-types.json b/tools/rule-types.json
index 1239e5f3f..eef001a20 100644
--- a/tools/rule-types.json
+++ b/tools/rule-types.json
@@ -33,6 +33,7 @@
     "func-name-matching": "suggestion",
     "func-names": "suggestion",
     "func-style": "suggestion",
+    "function-call-argument-newline": "layout",
     "function-paren-newline": "layout",
     "generator-star-spacing": "layout",
     "getter-return": "problem",


Test patch:
diff --git a/tests/lib/rules/accessor-pairs.js b/tests/lib/rules/accessor-pairs.js
index 42ca8461d..4f55cd10e 100644
--- a/tests/lib/rules/accessor-pairs.js
+++ b/tests/lib/rules/accessor-pairs.js
@@ -18,26 +18,301 @@ const rule = require("../../../lib/rules/accessor-pairs"),
 
 const ruleTester = new RuleTester();
 
-const getterError = { messageId: "getter" };
-const setterError = { messageId: "setter" };
-
 ruleTester.run("accessor-pairs", rule, {
     valid: [
-        "var o = { a: 1 };",
-        "var o = {\n get a() {\n return val; \n} \n};",
-        "var o = {\n set a(value) {\n val = value; \n},\n get a() {\n return val; \n} \n};",
-        "var o = {a: 1};\n Object.defineProperty(o, 'b', \n{set: function(value) {\n val = value; \n},\n get: function() {\n return val; \n} \n});",
+
+        //------------------------------------------------------------------------------
+        // General
+        //------------------------------------------------------------------------------
+
+        // Does not check object patterns
         {
-            code: "var expr = 'foo';  var o = { set [expr](value) { val = value; }, get [expr]() { return val; } };",
+            code: "var { get: foo } = bar; ({ set: foo } = bar);",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
             parserOptions: { ecmaVersion: 6 }
         },
         {
-            code: "var o = {\n set a(value) {\n val = value; \n} \n};",
-            options: [{
-                setWithoutGet: false
-            }]
+            code: "var { set } = foo; ({ get } = foo);",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        //------------------------------------------------------------------------------
+        // Object literals
+        //------------------------------------------------------------------------------
+
+        // Test default settings, this would be an error if `getWithoutSet` was set to `true`
+        "var o = { get a() {} }",
+
+        // No accessors
+        {
+            code: "var o = {};",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { a: 1 };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { a };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { a: get };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { a: set };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get: function(){} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { set: function(foo){} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { set };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { [get]: function() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { [set]: function(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { set(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        // Disabled options
+        {
+            code: "var o = { get a() {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: false }]
+        },
+        {
+            code: "var o = { get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: false }]
+        },
+        {
+            code: "var o = { set a(foo) {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: false }]
+        },
+        {
+            code: "var o = { set a(foo) {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { set a(foo) {} };",
+            options: [{ setWithoutGet: false }]
+        },
+
+        // Valid pairs with identifiers
+        {
+            code: "var o = { get a() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: false }]
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { set a(foo) {}, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
         },
 
+        // Valid pairs with statically computed names
+        {
+            code: "var o = { get 'a'() {}, set 'a'(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get a() {}, set 'a'(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get ['abc']() {}, set ['abc'](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [1e2]() {}, set 100(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get abc() {}, set [`abc`](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get ['123']() {}, set 123(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        // Valid pairs with expressions
+        {
+            code: "var o = { get [a]() {}, set [a](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [a]() {}, set [(a)](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [(a)]() {}, set [a](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [a]() {}, set [ a ](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [/*comment*/a/*comment*/]() {}, set [a](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [f()]() {}, set [f()](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [f(a)]() {}, set [f(a)](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [a + b]() {}, set [a + b](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get [`${a}`]() {}, set [`${a}`](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        // Multiple valid pairs in the same literal
+        {
+            code: "var o = { get a() {}, set a(foo) {}, get b() {}, set b(bar) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get a() {}, set c(foo) {}, set a(bar) {}, get b() {}, get c() {}, set b(baz) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+
+        // Valid pairs with other elements
+        {
+            code: "var o = { get a() {}, set a(foo) {}, b: bar };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }]
+        },
+        {
+            code: "var o = { get a() {}, b, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get a() {}, ...b, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 }
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {}, ...a };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 }
+        },
+
+        // Duplicate keys. This is the responsibility of no-dupe-keys, but this rule still checks is there the other accessor kind.
+        {
+            code: "var o = { get a() {}, get a() {}, set a(foo) {}, };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {}, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { set a(bar) {}, get a() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get a() {}, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: false }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { set a(foo) {}, set a(foo) {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { get a() {}, set a(foo) {}, a };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var o = { a, get a() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        /*
+         * This should be actually invalid by this rule!
+         * This code creates a property with the setter only, the getter will be ignored.
+         * It's treated as 3 attempts to define the same key, and the last wins.
+         * However, this edge case is not covered, it should be reported by no-dupe-keys anyway.
+         */
+        {
+            code: "var o = { get a() {}, a:1, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        //------------------------------------------------------------------------------
+        // Property descriptors
+        //------------------------------------------------------------------------------
+
+        "var o = {a: 1};\n Object.defineProperty(o, 'b', \n{set: function(value) {\n val = value; \n},\n get: function() {\n return val; \n} \n});",
+
         // https://github.com/eslint/eslint/issues/3262
         "var o = {set: function() {}}",
         "Object.defineProperties(obj, {set: {value: function() {}}});",
@@ -46,38 +321,494 @@ ruleTester.run("accessor-pairs", rule, {
         { code: "var o = {[set]: function() {}}", parserOptions: { ecmaVersion: 6 } },
         { code: "var set = 'value'; Object.defineProperty(obj, 'foo', {[set]: function(value) {}});", parserOptions: { ecmaVersion: 6 } }
     ],
+
     invalid: [
+
+        //------------------------------------------------------------------------------
+        // Object literals
+        //------------------------------------------------------------------------------
+
+        // Test default settings
+        {
+            code: "var o = { set a(value) {} };",
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property" }]
+        },
+
+        // Test that the options do not affect each other
+        {
+            code: "var o = { set a(value) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: false }],
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set a(value) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get a() {} };",
+            options: [{ setWithoutGet: false, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get a() {} };",
+            options: [{ getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property" }]
+        },
+
+        // Various kinds of the getter's key
+        {
+            code: "var o = { get abc() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get 'abc'() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get 123() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter '123'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get 1e2() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter '100'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get ['abc']() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get [`abc`]() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get [123]() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter '123'.", type: "Property" }]
+        },
+        {
+            code: "var o = { get [abc]() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter.", type: "Property" }]
+        },
+        {
+            code: "var o = { get [f(abc)]() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter.", type: "Property" }]
+        },
+        {
+            code: "var o = { get [a + b]() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter.", type: "Property" }]
+        },
+
+        // Various kinds of the setter's key
+        {
+            code: "var o = { set abc(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set 'abc'(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set 123(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter '123'.", type: "Property" }]
+        },
         {
-            code: "var o = {\n set a(value) {\n val = value; \n} \n};",
-            errors: [getterError]
+            code: "var o = { set 1e2(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter '100'.", type: "Property" }]
         },
         {
-            code: "var o = {\n get a() {\n return val; \n} \n};",
-            options: [{
-                getWithoutSet: true
-            }],
-            errors: [setterError]
+            code: "var o = { set ['abc'](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set [`abc`](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter 'abc'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set [123](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter '123'.", type: "Property" }]
+        },
+        {
+            code: "var o = { set [abc](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter.", type: "Property" }]
+        },
+        {
+            code: "var o = { set [f(abc)](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter.", type: "Property" }]
+        },
+        {
+            code: "var o = { set [a + b](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter.", type: "Property" }]
+        },
+
+        // Different keys
+        {
+            code: "var o = { get a() {}, set b(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'b'.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { set a(foo) {}, get b() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 11 },
+                { message: "Setter is not present for getter 'b'.", type: "Property", column: 26 }
+            ]
         },
+        {
+            code: "var o = { get 1() {}, set b(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter '1'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'b'.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { get a() {}, set 1(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter '1'.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { get a() {}, set 'a '(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'a '.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { get ' a'() {}, set 'a'(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter ' a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 26 }
+            ]
+        },
+        {
+            code: "var o = { get ''() {}, set ' '(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { messageId: "missingSetterInObjectLiteral", type: "Property", column: 11 }, // TODO: Change to message when getFunctionNameWithKind gets fixed
+                { message: "Getter is not present for setter ' '.", type: "Property", column: 24 }
+            ]
+        },
+        {
+            code: "var o = { get ''() {}, set null(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { messageId: "missingSetterInObjectLiteral", type: "Property", column: 11 }, // TODO: Change to message when getFunctionNameWithKind gets fixed
+                { message: "Getter is not present for setter 'null'.", type: "Property", column: 24 }
+            ]
+        },
+        {
+            code: "var o = { get [`a`]() {}, set b(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'b'.", type: "Property", column: 27 }
+            ]
+        },
+        {
+            code: "var o = { get [a]() {}, set [b](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter.", type: "Property", column: 25 }
+            ]
+        },
+        {
+            code: "var o = { get [a]() {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 25 }
+            ]
+        },
+        {
+            code: "var o = { get a() {}, set [a](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { get [a + b]() {}, set [a - b](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter.", type: "Property", column: 29 }
+            ]
+        },
+        {
+            code: "var o = { get [`${0} `]() {}, set [`${0}`](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter.", type: "Property", column: 31 }
+            ]
+        },
+
+        // Multiple invalid of same and different kinds
+        {
+            code: "var o = { get a() {}, get b() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Setter is not present for getter 'b'.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { set a(foo) {}, set b(bar) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'b'.", type: "Property", column: 26 }
+            ]
+        },
+        {
+            code: "var o = { get a() {}, set b(foo) {}, set c(foo) {}, get d() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'b'.", type: "Property", column: 23 },
+                { message: "Getter is not present for setter 'c'.", type: "Property", column: 38 },
+                { message: "Setter is not present for getter 'd'.", type: "Property", column: 53 }
+            ]
+        },
+
+        // Checks per object literal
+        {
+            code: "var o1 = { get a() {} }, o2 = { set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 12 },
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 33 }
+            ]
+        },
+        {
+            code: "var o1 = { set a(foo) {} }, o2 = { get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 12 },
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 36 }
+            ]
+        },
+
+        // Combinations or valid and invalid
+        {
+            code: "var o = { get a() {}, get b() {}, set b(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { get b() {}, get a() {}, set b(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 23 }]
+        },
+        {
+            code: "var o = { get b() {}, set b(foo) {}, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 38 }]
+        },
+        {
+            code: "var o = { set a(foo) {}, get b() {}, set b(bar) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { get b() {}, set a(foo) {}, set b(bar) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 23 }]
+        },
+        {
+            code: "var o = { get b() {}, set b(bar) {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 38 }]
+        },
+        {
+            code: "var o = { get v1() {}, set i1(foo) {}, get v2() {}, set v2(bar) {}, get i2() {}, set v1(baz) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            errors: [
+                { message: "Getter is not present for setter 'i1'.", type: "Property", column: 24 },
+                { message: "Setter is not present for getter 'i2'.", type: "Property", column: 69 }
+            ]
+        },
+
+        // In the case of duplicates which don't have the other kind, all nodes are reported
+        {
+            code: "var o = { get a() {}, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 11 },
+                { message: "Setter is not present for getter 'a'.", type: "Property", column: 23 }
+            ]
+        },
+        {
+            code: "var o = { set a(foo) {}, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 11 },
+                { message: "Getter is not present for setter 'a'.", type: "Property", column: 26 }
+            ]
+        },
+
+        // Other elements or even value property duplicates in the same literal do not affect this rule
+        {
+            code: "var o = { a, get b() {}, c };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter 'b'.", type: "Property", column: 14 }]
+        },
+        {
+            code: "var o = { a, get b() {}, c, set d(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Setter is not present for getter 'b'.", type: "Property", column: 14 },
+                { message: "Getter is not present for setter 'd'.", type: "Property", column: 29 }
+            ]
+        },
+        {
+            code: "var o = { get a() {}, a:1 };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { a, get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 14 }]
+        },
+        {
+            code: "var o = { set a(foo) {}, a:1 };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { a, set a(foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 14 }]
+        },
+        {
+            code: "var o = { get a() {}, ...b };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { get a() {}, ...a };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [{ message: "Setter is not present for getter 'a'.", type: "Property", column: 11 }]
+        },
+        {
+            code: "var o = { set a(foo) {}, ...a };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [{ message: "Getter is not present for setter 'a'.", type: "Property", column: 11 }]
+        },
+
+        // Full location tests
+        {
+            code: "var o = { get a() {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [{
+                message: "Setter is not present for getter 'a'.",
+                type: "Property",
+                line: 1,
+                column: 11,
+                endLine: 1,
+                endColumn: 16
+            }]
+        },
+        {
+            code: "var o = {\n  set [\n a](foo) {} };",
+            options: [{ setWithoutGet: true, getWithoutSet: true }],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: [{
+                message: "Getter is not present for setter.",
+                type: "Property",
+                line: 2,
+                column: 3,
+                endLine: 3,
+                endColumn: 4
+            }]
+        },
+
+        //------------------------------------------------------------------------------
+        // Property descriptors
+        //------------------------------------------------------------------------------
+
         {
             code: "var o = {d: 1};\n Object.defineProperty(o, 'c', \n{set: function(value) {\n val = value; \n} \n});",
-            errors: [getterError]
+            errors: [{ message: "Getter is not present in property descriptor.", type: "ObjectExpression" }]
         },
         {
             code: "Reflect.defineProperty(obj, 'foo', {set: function(value) {}});",
-            errors: [getterError]
+            errors: [{ message: "Getter is not present in property descriptor.", type: "ObjectExpression" }]
         },
         {
             code: "Object.defineProperties(obj, {foo: {set: function(value) {}}});",
-            errors: [getterError]
+            errors: [{ message: "Getter is not present in property descriptor.", type: "ObjectExpression" }]
         },
         {
             code: "Object.create(null, {foo: {set: function(value) {}}});",
-            errors: [getterError]
-        },
-        {
-            code: "var expr = 'foo';  var o = { set [expr](value) { val = value; } };",
-            parserOptions: { ecmaVersion: 6 },
-            errors: [getterError]
+            errors: [{ message: "Getter is not present in property descriptor.", type: "ObjectExpression" }]
         }
     ]
 });
diff --git a/tests/lib/rules/class-methods-use-this.js b/tests/lib/rules/class-methods-use-this.js
index 852124245..5238b9d68 100644
--- a/tests/lib/rules/class-methods-use-this.js
+++ b/tests/lib/rules/class-methods-use-this.js
@@ -37,49 +37,49 @@ ruleTester.run("class-methods-use-this", rule, {
             code: "class A { foo() {} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() {/**this**/} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() {var a = function () {this};} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() {var a = function () {var b = function(){this}};} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() {window.this} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() {that.this = 'this';} }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
             code: "class A { foo() { () => undefined; } }",
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
@@ -87,7 +87,7 @@ ruleTester.run("class-methods-use-this", rule, {
             options: [{ exceptMethods: ["bar"] }],
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "foo" } }
+                { type: "FunctionExpression", line: 1, column: 14, messageId: "missingThis", data: { name: "method 'foo'" } }
             ]
         },
         {
@@ -95,7 +95,30 @@ ruleTester.run("class-methods-use-this", rule, {
             options: [{ exceptMethods: ["foo"] }],
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { type: "FunctionExpression", line: 1, column: 34, messageId: "missingThis", data: { name: "hasOwnProperty" } }
+                { type: "FunctionExpression", line: 1, column: 34, messageId: "missingThis", data: { name: "method 'hasOwnProperty'" } }
+            ]
+        },
+        {
+            code: "class A { [foo]() {} }",
+            options: [{ exceptMethods: ["foo"] }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { type: "FunctionExpression", line: 1, column: 16, messageId: "missingThis", data: { name: "method" } }
+            ]
+        },
+        {
+            code: "class A { foo(){} 'bar'(){} 123(){} [`baz`](){} [a](){} [f(a)](){} get quux(){} set[a](b){} *quuux(){} }",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                { message: "Expected 'this' to be used by class method 'foo'.", type: "FunctionExpression", column: 14 },
+                { message: "Expected 'this' to be used by class method 'bar'.", type: "FunctionExpression", column: 24 },
+                { message: "Expected 'this' to be used by class method '123'.", type: "FunctionExpression", column: 32 },
+                { message: "Expected 'this' to be used by class method 'baz'.", type: "FunctionExpression", column: 44 },
+                { message: "Expected 'this' to be used by class method.", type: "FunctionExpression", column: 52 },
+                { message: "Expected 'this' to be used by class method.", type: "FunctionExpression", column: 63 },
+                { message: "Expected 'this' to be used by class getter 'quux'.", type: "FunctionExpression", column: 76 },
+                { message: "Expected 'this' to be used by class setter.", type: "FunctionExpression", column: 87 },
+                { message: "Expected 'this' to be used by class generator method 'quuux'.", type: "FunctionExpression", column: 99 }
             ]
         }
     ]
diff --git a/tests/lib/rules/dot-notation.js b/tests/lib/rules/dot-notation.js
index 490a0956c..5532ea358 100644
--- a/tests/lib/rules/dot-notation.js
+++ b/tests/lib/rules/dot-notation.js
@@ -57,7 +57,8 @@ ruleTester.run("dot-notation", rule, {
         "a.null;",
         "a[undefined];",
         "a[void 0];",
-        "a[b()];"
+        "a[b()];",
+        { code: "a[/(?<zero>0)/];", parserOptions: { ecmaVersion: 2018 } }
     ],
     invalid: [
         {
@@ -82,6 +83,16 @@ ruleTester.run("dot-notation", rule, {
             output: "a.null;",
             errors: [{ messageId: "useDot", data: { key: "null" } }]
         },
+        {
+            code: "a[true];",
+            output: "a.true;",
+            errors: [{ messageId: "useDot", data: { key: "true" } }]
+        },
+        {
+            code: "a[false];",
+            output: "a.false;",
+            errors: [{ messageId: "useDot", data: { key: "false" } }]
+        },
         {
             code: "a['b'];",
             output: "a.b;",
diff --git a/tests/lib/rules/function-call-argument-newline.js b/tests/lib/rules/function-call-argument-newline.js
new file mode 100644
index 000000000..2871534e7
--- /dev/null
+++ b/tests/lib/rules/function-call-argument-newline.js
@@ -0,0 +1,386 @@
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const rule = require("../../../lib/rules/function-call-argument-newline"),
+    { RuleTester } = require("../../../lib/rule-tester");
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester();
+
+ruleTester.run("function-call-argument-newline", rule, {
+    valid: [
+
+        /* early return */
+        "fn()",
+        "fn(a)",
+        "new Foo()",
+        "new Foo(b)",
+
+        /* default ("always") */
+        "fn(a,\n\tb)",
+
+        /* "always" */
+        { code: "fn(a,\n\tb)", options: ["always"] },
+        { code: "fn(\n\ta,\n\tb\n)", options: ["always"] },
+        { code: "fn(\n\ta,\n\tb,\n\tc\n)", options: ["always"] },
+        {
+            code: "fn(\n\ta,\n\tb,\n\t[\n\t\t1,\n\t\t2\n\t]\n)",
+            options: ["always"]
+        },
+        {
+            code: "fn(\n\ta,\n\tb,\n\t{\n\t\ta: 1,\n\t\tb: 2\n\t}\n)",
+            options: ["always"]
+        },
+        {
+            code: "fn(\n\ta,\n\tb,\n\tfunction (x) {\n\t\tx()\n\t}\n)",
+            options: ["always"]
+        },
+        {
+            code: "fn(\n\ta,\n\tb,\n\tx => {\n\t\tx()\n\t}\n)",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        /* "never" */
+        { code: "fn(a, b)", options: ["never"] },
+        { code: "fn(\n\ta, b\n)", options: ["never"] },
+        { code: "fn(a, b, c)", options: ["never"] },
+        { code: "fn(a, b, [\n\t1,\n\t2\n])", options: ["never"] },
+        { code: "fn(a, b, {\n\ta: 1,\n\tb: 2\n})", options: ["never"] },
+        { code: "fn(a, b, function (x) {\n\tx()\n})", options: ["never"] },
+        {
+            code: "fn(a, b, x => {\n\tx()\n})",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+
+        /* "consistent" */
+        { code: "fn(a, b, c)", options: ["consistent"] },
+        { code: "fn(a,\n\tb,\n\tc)", options: ["consistent"] }
+    ],
+    invalid: [
+
+        /* default ("always") */
+        {
+            code: "fn(a, b)",
+            output: "fn(a,\nb)",
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                }
+            ]
+        },
+
+        /* "always" */
+        {
+            code: "fn(a, b)",
+            output: "fn(a,\nb)",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                }
+            ]
+        },
+        {
+            code: "fn(a, b, c)",
+            output: "fn(a,\nb,\nc)",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                },
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "fn(a, b, [\n\t1,\n\t2\n])",
+            output: "fn(a,\nb,\n[\n\t1,\n\t2\n])",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                },
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "fn(a, b, {\n\ta: 1,\n\tb: 2\n})",
+            output: "fn(a,\nb,\n{\n\ta: 1,\n\tb: 2\n})",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                },
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "fn(a, b, function (x) {\n\tx()\n})",
+            output: "fn(a,\nb,\nfunction (x) {\n\tx()\n})",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                },
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+        {
+            code: "fn(a, b, x => {\n\tx()\n})",
+            output: "fn(a,\nb,\nx => {\n\tx()\n})",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 1,
+                    endColumn: 7
+                },
+                {
+                    messageId: "missingLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 1,
+                    endColumn: 10
+                }
+            ]
+        },
+
+        /* "never" */
+        {
+            code: "fn(a,\n\tb)",
+            output: "fn(a, b)",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb,\n\tc)",
+            output: "fn(a, b, c)",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                },
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb,\n\t[\n\t\t1,\n\t\t2\n])",
+            output: "fn(a, b, [\n\t\t1,\n\t\t2\n])",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                },
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb,\n\t{\n\t\ta: 1,\n\t\tb: 2\n})",
+            output: "fn(a, b, {\n\t\ta: 1,\n\t\tb: 2\n})",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                },
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb,\n\tfunction (x) {\n\t\tx()\n})",
+            output: "fn(a, b, function (x) {\n\t\tx()\n})",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                },
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb,\n\tx => {\n\t\tx()\n})",
+            output: "fn(a, b, x => {\n\t\tx()\n})",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 6,
+                    endLine: 2,
+                    endColumn: 2
+                },
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 3,
+                    endColumn: 2
+                }
+            ]
+        },
+
+        /* "consistent" */
+        {
+            code: "fn(a, b,\n\tc)",
+            output: "fn(a, b, c)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "unexpectedLineBreak",
+                    line: 1,
+                    column: 9,
+                    endLine: 2,
+                    endColumn: 2
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb, c)",
+            output: "fn(a,\n\tb,\nc)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 2,
+                    column: 4,
+                    endLine: 2,
+                    endColumn: 5
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb /* comment */, c)",
+            output: "fn(a,\n\tb /* comment */,\nc)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 2,
+                    column: 18,
+                    endLine: 2,
+                    endColumn: 19
+                }
+            ]
+        },
+        {
+            code: "fn(a,\n\tb, /* comment */ c)",
+            output: "fn(a,\n\tb, /* comment */\nc)",
+            options: ["consistent"],
+            errors: [
+                {
+                    messageId: "missingLineBreak",
+                    line: 2,
+                    column: 18,
+                    endLine: 2,
+                    endColumn: 19
+                }
+            ]
+        }
+    ]
+});
diff --git a/tests/lib/rules/no-dupe-keys.js b/tests/lib/rules/no-dupe-keys.js
index 518f6c36c..a0a1e7a8c 100644
--- a/tests/lib/rules/no-dupe-keys.js
+++ b/tests/lib/rules/no-dupe-keys.js
@@ -22,6 +22,11 @@ ruleTester.run("no-dupe-keys", rule, {
     valid: [
         "var foo = { __proto__: 1, two: 2};",
         "var x = { foo: 1, bar: 2 };",
+        "var x = { '': 1, bar: 2 };",
+        "var x = { '': 1, ' ': 2 };",
+        { code: "var x = { '': 1, [null]: 2 };", parserOptions: { ecmaVersion: 6 } },
+        { code: "var x = { '': 1, [a]: 2 };", parserOptions: { ecmaVersion: 6 } },
+        { code: "var x = { [a]: 1, [a]: 2 };", parserOptions: { ecmaVersion: 6 } },
         "+{ get a() { }, set a(b) { } };",
         { code: "var x = { a: b, [a]: b };", parserOptions: { ecmaVersion: 6 } },
         { code: "var x = { a: b, ...c }", parserOptions: { ecmaVersion: 2018 } },
@@ -32,6 +37,8 @@ ruleTester.run("no-dupe-keys", rule, {
     invalid: [
         { code: "var x = { a: b, ['a']: b };", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "unexpected", data: { name: "a" }, type: "ObjectExpression" }] },
         { code: "var x = { y: 1, y: 2 };", errors: [{ messageId: "unexpected", data: { name: "y" }, type: "ObjectExpression" }] },
+        { code: "var x = { '': 1, '': 2 };", errors: [{ messageId: "unexpected", data: { name: "" }, type: "ObjectExpression" }] },
+        { code: "var x = { '': 1, [``]: 2 };", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "unexpected", data: { name: "" }, type: "ObjectExpression" }] },
         { code: "var foo = { 0x1: 1, 1: 2};", errors: [{ messageId: "unexpected", data: { name: "1" }, type: "ObjectExpression" }] },
         { code: "var x = { \"z\": 1, z: 2 };", errors: [{ messageId: "unexpected", data: { name: "z" }, type: "ObjectExpression" }] },
         { code: "var foo = {\n  bar: 1,\n  bar: 1,\n}", errors: [{ messageId: "unexpected", data: { name: "bar" }, line: 3, column: 3 }] },
diff --git a/tests/lib/rules/no-duplicate-case.js b/tests/lib/rules/no-duplicate-case.js
index 21f6267a0..a6e8e0ff3 100644
--- a/tests/lib/rules/no-duplicate-case.js
+++ b/tests/lib/rules/no-duplicate-case.js
@@ -29,71 +29,105 @@ ruleTester.run("no-duplicate-case", rule, {
         "var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 2).p1: break; default: break;}",
         "var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a == 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;}",
         "var a = 1, f1 = function() { return { p1: 1 } }, f2 = function() { return { p1: 2 } }; switch (a) {case f1().p1: break; case f2().p1: break; default: break;}",
-        "var a = [1,2]; switch(a.toString()){case ([1,2]).toString():break; case ([1]).toString():break; default:break;}"
+        "var a = [1,2]; switch(a.toString()){case ([1,2]).toString():break; case ([1]).toString():break; default:break;}",
+        "switch(a) { case a: break; } switch(a) { case a: break; }",
+        "switch(a) { case toString: break; }"
     ],
     invalid: [
         {
             code: "var a = 1; switch (a) {case 1: break; case 1: break; case 2: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 39
             }]
         },
         {
             code: "var a = '1'; switch (a) {case '1': break; case '1': break; case '2': break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 43
             }]
         },
         {
             code: "var a = 1, one = 1; switch (a) {case one: break; case one: break; case 2: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 50
             }]
         },
         {
             code: "var a = 1, p = {p: {p1: 1, p2: 1}}; switch (a) {case p.p.p1: break; case p.p.p1: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 69
             }]
         },
         {
             code: "var a = 1, f = function(b) { return b ? { p1: 1 } : { p1: 2 }; }; switch (a) {case f(true).p1: break; case f(true).p1: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 103
             }]
         },
         {
             code: "var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a + 1).p1: break; case f(a + 1).p1: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 87
             }]
         },
         {
             code: "var a = 1, f = function(s) { return { p1: s } }; switch (a) {case f(a === 1 ? 2 : 3).p1: break; case f(a === 1 ? 2 : 3).p1: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 97
             }]
         },
         {
             code: "var a = 1, f1 = function() { return { p1: 1 } }; switch (a) {case f1().p1: break; case f1().p1: break; default: break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 83
             }]
         },
         {
             code: "var a = [1, 2]; switch(a.toString()){case ([1, 2]).toString():break; case ([1, 2]).toString():break; default:break;}",
             errors: [{
                 messageId: "unexpected",
-                type: "SwitchCase"
+                type: "SwitchCase",
+                column: 70
             }]
+        },
+        {
+            code: "switch (a) { case a: case a: }",
+            errors: [{
+                messageId: "unexpected",
+                type: "SwitchCase",
+                column: 22
+            }]
+        },
+        {
+            code: "switch (a) { case a: break; case b: break; case a: break; case c: break; case a: break; }",
+            errors: [
+                {
+                    messageId: "unexpected",
+                    type: "SwitchCase",
+                    column: 44
+                },
+                {
+                    messageId: "unexpected",
+                    type: "SwitchCase",
+                    column: 74
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/no-extra-bind.js b/tests/lib/rules/no-extra-bind.js
index e9c72bca6..cc2b164e8 100644
--- a/tests/lib/rules/no-extra-bind.js
+++ b/tests/lib/rules/no-extra-bind.js
@@ -21,6 +21,7 @@ const errors = [{ messageId: "unexpected", type: "CallExpression" }];
 ruleTester.run("no-extra-bind", rule, {
     valid: [
         "var a = function(b) { return b }.bind(c, d)",
+        { code: "var a = function(b) { return b }.bind(...c)", parserOptions: { ecmaVersion: 6 } },
         "var a = function() { this.b }()",
         "var a = function() { this.b }.foo()",
         "var a = f.bind(a)",
diff --git a/tests/lib/rules/no-extra-boolean-cast.js b/tests/lib/rules/no-extra-boolean-cast.js
index 4d2890e84..129329ff0 100644
--- a/tests/lib/rules/no-extra-boolean-cast.js
+++ b/tests/lib/rules/no-extra-boolean-cast.js
@@ -227,6 +227,314 @@ ruleTester.run("no-extra-boolean-cast", rule, {
                 messageId: "unexpectedCall",
                 type: "CallExpression"
             }]
+        },
+        {
+            code: "if (!Boolean()) { foo() }",
+            output: "if (true) { foo() }",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "while (!Boolean()) { foo() }",
+            output: "while (true) { foo() }",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "var foo = Boolean() ? bar() : baz()",
+            output: "var foo = false ? bar() : baz()",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if (Boolean()) { foo() }",
+            output: "if (false) { foo() }",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "while (Boolean()) { foo() }",
+            output: "while (false) { foo() }",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+
+        // Adjacent tokens tests
+        {
+            code: "void!Boolean()",
+            output: "void true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "void! Boolean()",
+            output: "void true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "typeof!Boolean()",
+            output: "typeof true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "(!Boolean())",
+            output: "(true)",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "+!Boolean()",
+            output: "+true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "void !Boolean()",
+            output: "void true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "void(!Boolean())",
+            output: "void(true)",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "void/**/!Boolean()",
+            output: "void/**/true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+
+        // Comments tests
+        {
+            code: "!/**/!!foo",
+            output: "!/**/foo",
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "!!/**/!foo",
+            output: null,
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "!!!/**/foo",
+            output: null,
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "!!!foo/**/",
+            output: "!foo/**/",
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "if(!/**/!foo);",
+            output: null,
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "(!!/**/foo ? 1 : 2)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "!/**/Boolean(foo)",
+            output: "!/**/foo",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean/**/(foo)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean(/**/foo)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean(foo/**/)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean(foo)/**/",
+            output: "!foo/**/",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(Boolean/**/(foo));",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "(Boolean(foo/**/) ? 1 : 2)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "/**/!Boolean()",
+            output: "/**/true",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!/**/Boolean()",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean/**/()",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean(/**/)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "!Boolean()/**/",
+            output: "true/**/",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(!/**/Boolean());",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "(!Boolean(/**/) ? 1 : 2)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(/**/Boolean());",
+            output: "if(/**/false);",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(Boolean/**/());",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(Boolean(/**/));",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "if(Boolean()/**/);",
+            output: "if(false/**/);",
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
+        },
+        {
+            code: "(Boolean/**/() ? 1 : 2)",
+            output: null,
+            errors: [{
+                messageId: "unexpectedCall",
+                type: "CallExpression"
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js
index 6c6eeb2a1..86b5ae4d6 100644
--- a/tests/lib/rules/no-extra-parens.js
+++ b/tests/lib/rules/no-extra-parens.js
@@ -1197,6 +1197,12 @@ ruleTester.run("no-extra-parens", rule, {
             "Identifier",
             1
         ),
+        invalid("let s = `${(v)}`", "let s = `${v}`", "Identifier"),
+        invalid("let s = `${(a, b)}`", "let s = `${a, b}`", "SequenceExpression"),
+        invalid("function foo(a = (b)) {}", "function foo(a = b) {}", "Identifier"),
+        invalid("const bar = (a = (b)) => a", "const bar = (a = b) => a", "Identifier"),
+        invalid("const [a = (b)] = []", "const [a = b] = []", "Identifier"),
+        invalid("const {a = (b)} = {}", "const {a = b} = {}", "Identifier"),
 
         // https://github.com/eslint/eslint/issues/11706 (also in valid[])
         {
diff --git a/tests/lib/rules/no-mixed-operators.js b/tests/lib/rules/no-mixed-operators.js
index d740b8562..4e822181f 100644
--- a/tests/lib/rules/no-mixed-operators.js
+++ b/tests/lib/rules/no-mixed-operators.js
@@ -47,7 +47,18 @@ ruleTester.run("no-mixed-operators", rule, {
         {
             code: "a * b / c",
             options: [{ allowSamePrecedence: true }]
-        }
+        },
+        {
+            code: "(a || b) ? c : d",
+            options: [{ groups: [["&&", "||", "?:"]] }]
+        },
+        {
+            code: "a || (b ? c : d)",
+            options: [{ groups: [["&&", "||", "?:"]] }]
+        },
+        "a || (b ? c : d)",
+        "(a || b) ? c : d",
+        "a || b ? c : d"
     ],
     invalid: [
         {
@@ -110,6 +121,38 @@ ruleTester.run("no-mixed-operators", rule, {
                 { column: 3, message: "Unexpected mix of '*' and '/'." },
                 { column: 7, message: "Unexpected mix of '*' and '/'." }
             ]
+        },
+        {
+            code: "a || b ? c : d",
+            options: [{ groups: [["&&", "||", "?:"]] }],
+            errors: [
+                { column: 3, message: "Unexpected mix of '||' and '?:'." },
+                { column: 8, message: "Unexpected mix of '||' and '?:'." }
+            ]
+        },
+        {
+            code: "a && b ? 1 : 2",
+            options: [{ groups: [["&&", "||", "?:"]] }],
+            errors: [
+                { column: 3, message: "Unexpected mix of '&&' and '?:'." },
+                { column: 8, message: "Unexpected mix of '&&' and '?:'." }
+            ]
+        },
+        {
+            code: "x ? a && b : 0",
+            options: [{ groups: [["&&", "||", "?:"]] }],
+            errors: [
+                { column: 3, message: "Unexpected mix of '?:' and '&&'." },
+                { column: 7, message: "Unexpected mix of '?:' and '&&'." }
+            ]
+        },
+        {
+            code: "x ? 0 : a && b",
+            options: [{ groups: [["&&", "||", "?:"]] }],
+            errors: [
+                { column: 3, message: "Unexpected mix of '?:' and '&&'." },
+                { column: 11, message: "Unexpected mix of '?:' and '&&'." }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/prefer-template.js b/tests/lib/rules/prefer-template.js
index 9e987a813..439b261cc 100644
--- a/tests/lib/rules/prefer-template.js
+++ b/tests/lib/rules/prefer-template.js
@@ -199,6 +199,16 @@ ruleTester.run("prefer-template", rule, {
             output: null,
             errors
         },
+        {
+            code: "foo + '\\0\\1'",
+            output: null,
+            errors
+        },
+        {
+            code: "foo + '\\08'",
+            output: null,
+            errors
+        },
         {
             code: "foo + '\\\\033'",
             output: "`${foo  }\\\\033`",
diff --git a/tests/lib/rules/require-await.js b/tests/lib/rules/require-await.js
index c63a1ef5e..7b43f3266 100644
--- a/tests/lib/rules/require-await.js
+++ b/tests/lib/rules/require-await.js
@@ -72,6 +72,10 @@ ruleTester.run("require-await", rule, {
             code: "(class { async foo() { doSomething() } })",
             errors: ["Async method 'foo' has no 'await' expression."]
         },
+        {
+            code: "(class { async ''() { doSomething() } })",
+            errors: ["Async method '' has no 'await' expression."]
+        },
         {
             code: "async function foo() { async () => { await doSomething() } }",
             errors: ["Async function 'foo' has no 'await' expression."]
diff --git a/tests/lib/rules/sort-keys.js b/tests/lib/rules/sort-keys.js
index de2eeef1e..eb26c5250 100644
--- a/tests/lib/rules/sort-keys.js
+++ b/tests/lib/rules/sort-keys.js
@@ -22,6 +22,10 @@ ruleTester.run("sort-keys", rule, {
     valid: [
 
         // default (asc)
+        { code: "var obj = {'':1, [``]:2}", options: [], parserOptions: { ecmaVersion: 6 } },
+        { code: "var obj = {[``]:1, '':2}", options: [], parserOptions: { ecmaVersion: 6 } },
+        { code: "var obj = {'':1, a:2}", options: [] },
+        { code: "var obj = {[``]:1, a:2}", options: [], parserOptions: { ecmaVersion: 6 } },
         { code: "var obj = {_:2, a:1, b:3} // default", options: [] },
         { code: "var obj = {a:1, b:3, c:2}", options: [] },
         { code: "var obj = {a:2, b:3, b_:1}", options: [] },
@@ -32,6 +36,8 @@ ruleTester.run("sort-keys", rule, {
 
         // ignore non-simple computed properties.
         { code: "var obj = {a:1, b:3, [a + b]: -1, c:2}", options: [], parserOptions: { ecmaVersion: 6 } },
+        { code: "var obj = {'':1, [f()]:2, a:3}", options: [], parserOptions: { ecmaVersion: 6 } },
+        { code: "var obj = {a:1, [b++]:2, '':3}", options: ["desc"], parserOptions: { ecmaVersion: 6 } },
 
         // ignore properties separated by spread properties
         { code: "var obj = {a:1, ...z, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
@@ -39,6 +45,8 @@ ruleTester.run("sort-keys", rule, {
         { code: "var obj = {...a, b:1, ...c, d:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
         { code: "var obj = {...a, b:1, ...d, ...c, e:2, z:5}", options: [], parserOptions: { ecmaVersion: 2018 } },
         { code: "var obj = {b:1, ...c, ...d, e:2}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {a:1, ...z, '':2}", options: [], parserOptions: { ecmaVersion: 2018 } },
+        { code: "var obj = {'':1, ...z, 'a':2}", options: ["desc"], parserOptions: { ecmaVersion: 2018 } },
 
         // not ignore properties not separated by spread properties
         { code: "var obj = {...z, a:1, b:1}", options: [], parserOptions: { ecmaVersion: 2018 } },
@@ -159,6 +167,15 @@ ruleTester.run("sort-keys", rule, {
     invalid: [
 
         // default (asc)
+        {
+            code: "var obj = {a:1, '':2} // default",
+            errors: ["Expected object keys to be in ascending order. '' should be before 'a'."]
+        },
+        {
+            code: "var obj = {a:1, [``]:2} // default",
+            parserOptions: { ecmaVersion: 6 },
+            errors: ["Expected object keys to be in ascending order. '' should be before 'a'."]
+        },
         {
             code: "var obj = {a:1, _:2, b:3} // default",
             errors: ["Expected object keys to be in ascending order. '_' should be before 'a'."]
@@ -234,6 +251,31 @@ ruleTester.run("sort-keys", rule, {
             parserOptions: { ecmaVersion: 2018 },
             errors: ["Expected object keys to be in descending order. 'b' should be before 'a'."]
         },
+        {
+            code: "var obj = {...z, '':1, a:2}",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 2018 },
+            errors: ["Expected object keys to be in descending order. 'a' should be before ''."]
+        },
+
+        // ignore non-simple computed properties, but their position shouldn't affect other comparisons.
+        {
+            code: "var obj = {a:1, [b+c]:2, '':3}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: ["Expected object keys to be in ascending order. '' should be before 'a'."]
+        },
+        {
+            code: "var obj = {'':1, [b+c]:2, a:3}",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: ["Expected object keys to be in descending order. 'a' should be before ''."]
+        },
+        {
+            code: "var obj = {b:1, [f()]:2, '':3, a:4}",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: ["Expected object keys to be in descending order. 'a' should be before ''."]
+        },
 
         // not ignore simple computed properties.
         {
@@ -478,6 +520,21 @@ ruleTester.run("sort-keys", rule, {
         },
 
         // desc
+        {
+            code: "var obj = {'':1, a:'2'} // desc",
+            options: ["desc"],
+            errors: [
+                "Expected object keys to be in descending order. 'a' should be before ''."
+            ]
+        },
+        {
+            code: "var obj = {[``]:1, a:'2'} // desc",
+            options: ["desc"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                "Expected object keys to be in descending order. 'a' should be before ''."
+            ]
+        },
         {
             code: "var obj = {a:1, _:2, b:3} // desc",
             options: ["desc"],
diff --git a/tests/lib/rules/utils/ast-utils.js b/tests/lib/rules/utils/ast-utils.js
index 678b7f274..314deeadf 100644
--- a/tests/lib/rules/utils/ast-utils.js
+++ b/tests/lib/rules/utils/ast-utils.js
@@ -671,7 +671,9 @@ describe("ast-utils", () => {
             "async () => {}": "async arrow function",
             "({ foo: function foo() {} })": "method 'foo'",
             "({ foo: function() {} })": "method 'foo'",
+            "({ '': function() {} })": "method ''",
             "({ ['foo']: function() {} })": "method 'foo'",
+            "({ ['']: function() {} })": "method ''",
             "({ [foo]: function() {} })": "method",
             "({ foo() {} })": "method 'foo'",
             "({ foo: function* foo() {} })": "generator method 'foo'",
@@ -1248,4 +1250,82 @@ describe("ast-utils", () => {
             assert.strictEqual(astUtils.equalTokens(ast.body[0], ast.body[1], sourceCode), false);
         });
     });
+
+    describe("hasOctalEscapeSequence", () => {
+
+        /* eslint-disable quote-props */
+        const expectedResults = {
+            "\\1": true,
+            "\\2": true,
+            "\\7": true,
+            "\\00": true,
+            "\\01": true,
+            "\\02": true,
+            "\\07": true,
+            "\\08": true,
+            "\\09": true,
+            "\\10": true,
+            "\\12": true,
+            " \\1": true,
+            "\\1 ": true,
+            "a\\1": true,
+            "\\1a": true,
+            "a\\1a": true,
+            " \\01": true,
+            "\\01 ": true,
+            "a\\01": true,
+            "\\01a": true,
+            "a\\01a": true,
+            "a\\08a": true,
+            "\\0\\1": true,
+            "\\0\\01": true,
+            "\\0\\08": true,
+            "\\n\\1": true,
+            "\\n\\01": true,
+            "\\n\\08": true,
+            "\\\\\\1": true,
+            "\\\\\\01": true,
+            "\\\\\\08": true,
+
+            "\\0": false,
+            "\\8": false,
+            "\\9": false,
+            " \\0": false,
+            "\\0 ": false,
+            "a\\0": false,
+            "\\0a": false,
+            "a\\8a": false,
+            "\\0\\8": false,
+            "\\8\\0": false,
+            "\\80": false,
+            "\\81": false,
+            "\\\\": false,
+            "\\\\0": false,
+            "\\\\01": false,
+            "\\\\08": false,
+            "\\\\1": false,
+            "\\\\12": false,
+            "\\\\\\0": false,
+            "\\\\\\8": false,
+            "\\0\\\\": false,
+            "0": false,
+            "1": false,
+            "8": false,
+            "01": false,
+            "08": false,
+            "80": false,
+            "12": false,
+            "\\a": false,
+            "\\n": false
+        };
+        /* eslint-enable quote-props */
+
+        Object.keys(expectedResults).forEach(key => {
+            it(`should return ${expectedResults[key]} for ${key}`, () => {
+                const ast = espree.parse(`"${key}"`);
+
+                assert.strictEqual(astUtils.hasOctalEscapeSequence(ast.body[0].expression.raw), expectedResults[key]);
+            });
+        });
+    });
 });
diff --git a/tests/lib/rules/yoda.js b/tests/lib/rules/yoda.js
index 89979ff58..d2c183477 100644
--- a/tests/lib/rules/yoda.js
+++ b/tests/lib/rules/yoda.js
@@ -50,6 +50,14 @@ ruleTester.run("yoda", rule, {
         }, {
             code: "if ('blue' < x.y && x.y < 'green') {}",
             options: ["never", { exceptRange: true }]
+        }, {
+            code: "if (0 < x[``] && x[``] < 100) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        }, {
+            code: "if (0 < x[''] && x[``] < 100) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 }
         }, {
             code: "if (0 <= x['y'] && x['y'] <= 100) {}",
             options: ["never", { exceptRange: true }]
@@ -332,6 +340,66 @@ ruleTester.run("yoda", rule, {
                 }
             ]
         },
+        {
+            code: "if (0 <= a[''] && a.b < 1) {}",
+            output: "if (a[''] >= 0 && a.b < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if (0 <= a[''] && a[' '] < 1) {}",
+            output: "if (a[''] >= 0 && a[' '] < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if (0 <= a[''] && a[null] < 1) {}",
+            output: "if (a[''] >= 0 && a[null] < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if (0 <= a[''] && a[b] < 1) {}",
+            output: "if (a[''] >= 0 && a[b] < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if (0 <= a[''] && a[b()] < 1) {}",
+            output: "if (a[''] >= 0 && a[b()] < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
         {
             code: "if (0 <= a[b()] && a[b()] < 1) {}",
             output: "if (a[b()] >= 0 && a[b()] < 1) {}",