ESLint v7.0.0 の変更点まとめ

前 [v6.8.0](https://qiita.com/mysticatea/items/cc40251136ce167a010b) | 次 [v7.1.0](https://qiita.com/mysticatea/items/46c93f13776b24b9d1b9)

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">ESLint v7.0.0 has been released 🎉<br><br>Thanks to everyone who helped make this release happen.<a href="https://t.co/AMhSuPxJIy">https://t.co/AMhSuPxJIy</a></p>&mdash; ESLint (@geteslint) <a href="https://twitter.com/geteslint/status/1258837727660904449?ref_src=twsrc%5Etfw">May 8, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ESLint `7.0.0` がリリースされました。
多数の互換性のない変更、ルール追加、オプション追加、そしてバグ修正が含まれています。

- [リリースノート (英語)](https://eslint.org/blog/2020/05/eslint-v7.0.0-released)
- [マイグレーションガイド (英語)](https://eslint.org/docs/user-guide/migrating-to-7.0.0)

以下は主要な変更点のまとめです。

**ユーザー向けの変更:**

- 💥 互換性がない変更
    - [Node.js 8.x/11.x のサポートを終了します](#nodejs-8x11x-のサポートを終了します)
    - [`overrides`設定に一致するファイルを自動的にリント対象にします](#overrides-設定に一致するファイルを自動的にリント対象にします)
    - [`--config` CLI オプションによる設定ファイル内の相対パスの扱いが変わります](#--config-cli-オプションによる設定ファイル内の相対パスの扱いが変わります)
    - [`--ignore-path` CLI オプションによる無視ファイル内のパスの扱いが変わります](#--ignore-path-cli-オプションによる無視ファイル内のパスの扱いが変わります)
    - [プラグインの読込元ディレクトリが変わります](#プラグインの読込元ディレクトリが変わります)
    - [デフォルトで無視するファイルが変わります](#デフォルトで無視するファイルが変わります)
    - [ディレクティブコメントに説明を書けます](#ディレクティブコメントに説明を書けます)
    - [`eslint:recommended`設定が有効にするルールが増えます](#eslintrecommended設定が有効にするルールが増えます)
    - [複数のルールのチェックが厳しくなります](#複数のルールのチェックが厳しくなります)
    - [複数の Node.js/CommonJS 向けルールが廃止されます](#複数の-nodejscommonjs-向けルールが廃止されます) 
    - [個人設定の利用がランタイム警告を出力します](#個人設定の利用がランタイム警告を出力します)
- 💡 新しいルール
    - [default-case-last](#default-case-last)
    - [no-restricted-exports](#no-restricted-exports)
    - [no-useless-backreference](#no-useless-backreference)
- 🔧 オプションが追加されたルール
    - [array-callback-return: `checkForEach`](#array-callback-return-checkforeach)
    - [array-element-newline: `ArrayExpression` and `ArrayPattern`](#array-element-newline-arrayexpression-and-arraypattern)
    - [indent: `offsetTernaryExpressions`](#indent-offsetternaryexpressions)
    - [indent: `outerIIFEBody:"off"`](#indent-outeriifebodyoff)
    - [no-extra-boolean-cast: `enforceForLogicalOperands`](#no-extra-boolean-cast-enforceforlogicaloperands)
    - [no-magic-numbers: BigInt in the `ignore` option](#no-magic-numbers-bigint-in-the-ignore-option)
    - [no-void: `allowAsStatement`](#no-void-allowasstatement)

**プラグイン開発者向けの変更:**

- 💥 互換性がない変更
    - [Node.js 8.x/11.x のサポートを終了します](#nodejs-8x11x-のサポートを終了します)
    - [`overrides`設定に一致するファイルを自動的にリント対象にします](#overrides-設定に一致するファイルを自動的にリント対象にします)
    - [プラグインの読込元ディレクトリが変わります](#プラグインの読込元ディレクトリが変わります)
    - [`RuleTester`のチェックが厳しくなります](#ruletester-のチェックが厳しくなります)
- ✨ 本体への機能追加
    - [`RuleTester`の`suggestions`テストで`messageId`/`data`を利用できます](#ruletester-のsuggestionsテストでmessageiddataを利用できます)

**ツール開発者 (エディタ拡張等) 向けの変更:**

- 💥 互換性がない変更
    - [Node.js 8.x/11.x のサポートを終了します](#nodejs-8x11x-のサポートを終了します)
    - [プラグインの読込元ディレクトリが変わります](#プラグインの読込元ディレクトリが変わります)
    - [新しい`ESLint`クラスが`CLIEngine`クラスを置き換えます](#新しい-eslint-クラスが-cliengine-クラスを置き換えます)

質問やバグ報告等ありましたら、お気軽にこちらまでお寄せください。

> 🏢 [日本語 Issue 管理リポジトリ](https://github.com/eslint/eslint-jp)
> 👫 [日本語サポート チャット](https://discord.com/channels/688543509199716507/718026066001788958) ([招待リンク](https://discord.gg/wfTnWvE))
> 🏢 [本家リポジトリ](https://github.com/eslint/eslint)
> 👫 [本家サポート チャット](https://discord.com/channels/688543509199716507) ([招待リンク](https://eslint.org/chat))

---

[PR] ESLint は開発リソースを確保するための寄付を募っています。
応援してくださると嬉しいです。

- [ESLint の GitHub Sponsors](https://github.com/sponsors/eslint)
- [私個人の GitHub Sponsors](https://github.com/sponsors/mysticatea)

# 💥 互換性がない変更

## Node.js 8.x/11.x のサポートを終了します
🔖 [RFC044], [#12700]

Node.js 8.x は 2019-12-31 に、11.x は 2019-06-01 に寿命を迎えたため、ESLint もそれらのバージョンのサポートを停止しました。

ESLint 7.0.0 がサポートする Node.js のバージョンは `^10.12.0 || >=12.0.0` となります。

**動作を元に戻したい場合:**

この変更は元に戻せません。
古い Node.js 環境をアップグレードするまで ESLint 7 を利用しないようにしてください。

## [overrides] 設定に一致するファイルを自動的にリント対象にします
🔖 [RFC020], [#12677]

これまで、`eslint lib` のようにディレクトリを指定したとき、ESLint はディレクトリ内の `*.js` ファイルをチェックしていました。Node.js が `*.cjs`/`*.mjs` 拡張子を導入したり、TypeScript や Vue.js でも ESLint を使うようになったりしたので、この仕様は不便でした。

ESLint 7.0.0 からは `*.js` に加えて [overrides] 設定にマッチするファイルもチェックします。例えば、

```yml:.eslintrc.yml
overrides:
- files: "*.js"
  extends: my-config-js
- files: "*.ts"
  extends: my-config-ts
```

のような設定がある場合、`eslint lib` コマンドは `lib` ディレクトリ内の `*.ts` ファイルもチェックします。

なお、`eslint lib/**` のように Glob パターンを指定した場合は今まで通りに動作しますのでご注意ください。[overrides] 設定にかかわらず Glob パターンにマッチする全てのファイルをチェックします。

**プラグイン開発者へ:**

あなたが管理するプラグインが `*.js` 以外のファイルを対象にするルールを提供する場合、`recommended`設定に [overrides] を追加すると利用者は便利かもしれません。

**動作を元に戻したい場合:**

今まで通り [overrides] 設定にかかわらず `*.js` だけをチェックしたい場合は、コマンドに `--ext js` を付与してください。`--ext` CLI オプションはこの新しい動作を上書きします。

## [--config] CLI オプションによる設定ファイル内の相対パスの扱いが変わります
🔖 [RFC037], [#12887]

`ignorePatterns`, `overrides[].files`, `overrides[].excludedFiles` 設定に相対パスがあった場合、その相対パスは設定ファイルの場所を基準に解決されます (共有設定内のそれら相対パスは、利用元の`.eslintrc.*`ファイルの場所を基準に解決されます)。

ESLint 7 でも基本的には同様です。しかし、[--config] CLI オプションで読み込んだファイルのみ、それら相対パスは CWD を基準に解決されるようになります。これは CWD にある仮想的な `.eslintrc.*` ファイルから `extends` されたのと同じ動作になります。

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、この変更が原因で意図しない挙動になった場合は、設定ファイル内の相対パスを書き換えてください。

## [--ignore-path] CLI オプションによる無視ファイル内のパスの扱いが変わります
🔖 [RFC037], [#12887]

`.eslintignore` ファイル内のパスは、そのファイルの場所を基準に解決されます。

ESLint 7 でも基本的には同様です。しかし、[--ignore-path] CLI オプションで読み込んだファイルのみ、それらパスは CWD を基準に解決されるようになります。

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、この変更が原因で意図しない挙動になった場合は、無視ファイル内のパスを書き換えてください。

## プラグインの読込元ディレクトリが変わります
🔖 [RFC047], [#12922]

ESLint 6 はすべての設定ファイルに書かれた `plugins` 設定のプラグインを `$CWD/node_modules` ディレクトリから読み込みます。この動作のため、エディタ拡張等に適切な CWD を設定しなければプラグインを利用できず、Monorepo スタイルの開発などで不便でした。

ESLint 7 では、設定ファイルに書かれた `plugins` 設定のプラグインは、各設定ファイルの場所を基準に読み込まれます。つまり、`packages/alice/.eslintrc.yml` ファイルに書かれたプラグインは `packages/alice/node_modules` ディレクトリから読み込まれます。

⚠️ 共有設定に書かれた `plugins` 設定のプラグインは、それを `extends` する利用元の `.eslintrc.*` ファイルの場所を基準に読み込まれます。そのため、共有設定からプラグインを利用する場合は引き続き `peerDependencies` を利用する必要があります。

**動作を元に戻したい場合:**

以前と同様に `$CWD/node_modules` ディレクトリからすべてのプラグインを読み込みたい場合は `--resolve-plugins-relative-to .` CLI オプションを利用してください (末尾のドットに注意)。
[--resolve-plugins-relative-to] CLI オプションはこの新しい動作を上書きします。

## デフォルトで無視するファイルが変わります
🔖 [RFC051], [#12888]

ESLint 6 がデフォルトで無視するファイルは、以下のパターンにマッチするファイルでした。

- `.*` (dotfiles)
- `/node_modules/**` (CWD にある `node_modules` ディレクトリ内)
- `/bower_components/**` (CWD にある `bower_components` ディレクトリ内)

ESLint 7 では、以下のように変更されます。

- `.!(eslintrc.*)` (`.eslintrc.*` 設定ファイルを除く dotfiles)
- `/**/node_modules/**` (`node_modules` ディレクトリ内)

**動作を元に戻したい場合:**

以前のように `.eslintrc.*` や `/bower_components/**` を無視したい、またはサブディレクトリの `node_modules` ディレクトリを無視したくない場合、`.eslintrc.*` 設定ファイルの `ignorePatterns` 設定を利用してください。

```yml:.eslintrc.yml
ignorePatterns:
- "!/*/**/node_modules/*"
- ".eslintrc.*"
- "/bower_components/*"
```

## ディレクティブコメントに説明を書けます
🔖 [RFC033], [#12699]

ディレクティブコメントとは、`/* eslint-disable */` のような ESLint の動作変更を指示するためのコメントのことです。ルールを無効にする場合、その理由を明示しておくことは良いことです。しかし、ディレクティブコメントの理由を書くための標準的な方法はありませんでした。

ESLint 7 では、空白文字に囲まれた2つ以上のハイフン ` -- ` を使ってディレクティブコメントに説明を追加できます。

```js:例

/* eslint-disable a-rule -- このルールはバグっている */
doSomething()

/* eslint-disable another-rule
----------------
ここでは...(略
 */
```

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、既存のディレクティブコメントに` -- `が含まれていて壊れてしまった場合は、その設定を設定ファイルの [overrides] 等に移してください。

## `eslint:recommended`設定が有効にするルールが増えます
🔖 [#12920]

新たに 3 つのルールが有効になります。

- [no-dupe-else-if] ... `if`-`else if` チェーンにおいて、前の `if` 文の条件を満たすために絶対に真にならない `if` 文を報告します。
- [no-import-assign] ... `import` 文で作成した変数への代入 (実行時エラーになる) を報告します。
- [no-setter-return] ... セッター内にある値を返す `return` を報告します。

**動作を元に戻したい場合:**

上記ルールを有効にしたくない場合は、設定ファイルに無効化する設定を追加してください。

```yml
extends: eslint:recommended
rules:
  no-dupe-else-if: "off"
  no-import-assign: "off"
  no-setter-return: "off"
```

## 複数のルールのチェックが厳しくなります
🔖 [#12195], [#12490], [#12608], [#12701], [#12757], [#12765], [#12806], [#12816], [#12837], [#12876], [#12913], [#12915], [#12919], [#12927]

以下のルールはより多くのエラーを報告するようになりました。

- [accessor-pairs] ... オブジェクト リテラルだけでなく、クラス メンバーもチェックするようになりました。
- [array-callback-return] ... ES2019 で追加された `flatMap()` メソッドもチェックするようになりました。
- [computed-property-spacing] ... オブジェクト リテラルだけでなく、クラス メンバーもチェックするようになりました。
- [func-names] ... デフォルト エクスポートの関数宣言も名前が省略可能であるため、関数式と同じように名前の有無をチェックするようになりました。
- [no-constant-condition] ... 埋込式がないか、全ての埋込式が定数であるテンプレートリテラルも定数であると認識するようになりました。
- [no-dupe-class-members] ... 計算されたプロパティ名が定数だった場合は重複チェックをするようになりました。
- [no-extra-parens] ... 代入演算子の左側についてもカッコの有無をチェックするようになりました。
- [no-implied-eval] ... `window.eval`のようなグローバルオブジェクトのプロパティアクセスも認識するようになりました。
- [no-iterator] ... 計算されたプロパティ名が定数だった場合も認識するようになりました。
- [no-magic-numbers] ... BigInt リテラルも認識するようになりました。
- [no-proto] ... 計算されたプロパティ名が定数だった場合も認識するようになりました。
- [no-restricted-modules] ... 埋込式がないか、全ての埋込式が定数であるテンプレートリテラルも定数であると認識するようになりました。
- [quote-props] ... プロパティ名としての BigInt リテラルも認識するようになりました。
- [radix] ... `parseInt()` 関数の第二引数が無効な数値 (`2`未満 or `36`より大きい) の場合もエラーを報告するようになりました。
- [use-isnan] ... `case` 句の `NaN` もエラー報告するようになりました。
- [yoda] ... BigInt リテラルとテンプレートリテラルも認識するようになりました。

他にもあるかも...

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、新しくエラーが報告された場合はコードを修正してください。

## 複数の Node.js/CommonJS 向けルールが廃止されます
🔖 [#12898]

Node.js/CommonJS 向けのルールが非推奨になりました。
代わりに [eslint-plugin-node] の対応するルールをご利用ください。

| 非推奨                  | 代わりのルール               |
| :---------------------- | :--------------------------- |
| [callback-return]       | [node/callback-return]       |
| [global-require]        | [node/global-require]        |
| [handle-callback-err]   | [node/handle-callback-err]   |
| [no-mixed-requires]     | [node/no-mixed-requires]     |
| [no-new-require]        | [node/no-new-require]        |
| [no-path-concat]        | [node/no-path-concat]        |
| [no-process-env]        | [node/no-process-env]        |
| [no-process-exit]       | [node/no-process-exit]       |
| [no-restricted-modules] | [node/no-restricted-require] |
| [no-sync]               | [node/no-sync]               |

**動作を元に戻したい場合:**

廃止されたルールは引き続き利用することができます。
ただし、廃止されたルールのコードは凍結され、今後はバグ修正や機能追加が行われません。早めの移行をお勧めします。

## 個人設定の利用がランタイム警告を出力します
🔖 [RFC032], [#12678]

個人設定とは、OS のホームディレクトリ (例: `/home/foo/`, `C:\Users\foo\`) に配置された `.eslintrc.*` 設定ファイルのことです。ESLint はプロジェクト内に設定ファイルが見つかると個人設定を (親ディレクトリであっても) 無視し、プロジェクト内に設定ファイルが見つからないと個人設定を (親ディレクトリでなくても) 利用します。

この個人設定の仕組みは [ESLint 6.7.0 で非推奨になりました](https://qiita.com/mysticatea/items/377b6ca6558dc253159b#%E9%9D%9E%E6%8E%A8%E5%A5%A8%E5%80%8B%E4%BA%BA%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)。

ESLint 7 では、個人設定の仕組みを利用すると標準エラー出力に非推奨警告を出力するようになります。

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、引き続きホームディレクトリの設定を利用したい場合は、[--config] CLI オプションで利用する設定を明示的に指定してください。もしくは、ホームディレクトリ以下に作業ディレクトリを作ってください (ESLint は親ディレクトリからも設定ファイルを探すので)。

## [RuleTester] のチェックが厳しくなります
🔖 [RFC025], [#12096], [#12955]

[RuleTester] がより多くの誤りを見つけるようになります。

- ルールが非標準の `node.start`/`node.end` プロパティを参照していた場合にテストが失敗するようになります。代わりに `node.range` プロパティを利用してください。
- ルールが自動修正を提供するにもかかわらず、自動修正のテスト (`output`) が書かれていない場合にテストが失敗するようになります。
- 期待されるエラー内容を指示する`errors`プロパティ内に未知のプロパティがあったとき、テストが失敗するようになります (typo でテストできてなかったという事がなくなります)。

**動作を元に戻したい場合:**

この変更は元に戻せません。
もし、新たにテストが失敗するようになった場合は、そのルールの処理かテスト内容を更新してください。

## 新しい [ESLint] クラスが [CLIEngine] クラスを置き換えます
🔖 [RFC040], [#12939]

Node.js アプリケーションから ESLint を利用するための API として [CLIEngine] クラスが提供されています。しかし、[CLIEngine] クラスは同期 API を提供するため、非同期の処理が必要な並列処理・ES Modules サポート・進捗表示などの機能追加の妨げになっていました。
また、[CLIEngine] という名前は最初に使うべきクラスであるとの印象を抱きにくく、ブラウザ向けの機能限定版 API である `Linter` クラスを先に試して「意図通りに動かない」と issue を作る人が多かったです。

ESLint 7 では、この [CLIEngine] クラスを廃止して、後継となる [ESLint] クラスを導入しました。[ESLint] クラスは [CLIEngine] と同等のメソッドを提供しますが、`Promise` を返す非同期メソッドになっています。メソッドの対応は以下の通りです。

| [CLIEngine]                                  | [ESLint]                            |
| :------------------------------------------- | :---------------------------------- |
| `executeOnFiles(patterns)`                   | `lintFiles(patterns)`               |
| `executeOnText(text, filePath, warnIgnored)` | `lintText(text, options)`           |
| `getFormatter(name)`                         | `loadFormatter(name)`               |
| `getConfigForFile(filePath)`                 | `calculateConfigForFile(filePath)`  |
| `isPathIgnored(filePath)`                    | `isPathIgnored(filePath)`           |
| `static outputFixes(results)`                | `static outputFixes(results)`       |
| `static getErrorResults(results)`            | `static getErrorResults(results)`   |
| `static getFormatter(name)`                  | (削除)                              |
| `addPlugin(pluginId, definition)`            | `plugins` コンストラクタ オプション |
| `getRules()`                                 | (未実装)                            |
| `resolveFileGlobPatterns()`                  | (削除)                              |

**動作を元に戻したい場合:**

現在 [CLIEngine] クラスは広く利用されているため、少なくとも1年間は削除されないはずです。引き続き利用することができます。
しかし、今後 [CLIEngine] のコードは凍結され、バグ修正や機能追加が行われません。例えば、ESLint 7.x では並列処理・ES Modules サポート・進捗表示の機能が追加される予定ですが、それらは [ESLint] クラスのみに実装され、[CLIEngine] クラスからは利用できません。早めの移行をお勧めします。

# ✨ 本体への機能追加

## [RuleTester] の`suggestions`テストで`messageId`/`data`を利用できます
🔖 [#12635]

[RuleTester] の`suggestions`のテストにて、`message`プロパティの代わりに`messageId`/`data`プロパティペアを用いてテストできるようになりました。

```js:例
const { RuleTester } = require("eslint")
const rule = require("../../../lib/rules/a-rule")

new RuleTester("a-rule", rule, {
    valid: [],
    invalid: [
        {
            code: "foo",
            errors: [{
                messageId: "error",
                data: { name: "foo" },
                suggestions: [{
                    messageId: "suggest",
                    data: { name: "foo" },
                    output: "bar"
                }],
            }],
        },
    ],
})
```

# 💡 新しいルール

## [default-case-last]
🔖 [#12668]

`default`句を`switch`文の末尾以外に書くことを禁止するルールが追加されました。

```js:例
/*eslint default-case-last: error */

//✘ BAD
switch (foo) {
  default:
    break
  case 0:
    break
  case 1:
    break
}
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgZGVmYXVsdC1jYXNlLWxhc3Q6IGVycm9yICovXG5cbi8v4pyYIEJBRFxuc3dpdGNoIChmb28pIHtcbiAgZGVmYXVsdDpcbiAgICBicmVha1xuICBjYXNlIDA6XG4gICAgYnJlYWtcbiAgY2FzZSAxOlxuICAgIGJyZWFrXG59XG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

## [no-restricted-exports]
🔖 [#12546]

特定の名前の ES Modules エクスポートを禁止するルールが追加されました。

```js:例
/*eslint no-restricted-exports: [error, { restrictedNamedExports: [foo, bar] }] */

//✘ BAD
export function foo() {}
let bar = 0
export { bar }
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tcmVzdHJpY3RlZC1leHBvcnRzOiBbZXJyb3IsIHsgcmVzdHJpY3RlZE5hbWVkRXhwb3J0czogW2ZvbywgYmFyXSB9XSAqL1xuXG4vL+KcmCBCQURcbmV4cG9ydCBmdW5jdGlvbiBmb28oKSB7fVxubGV0IGJhciA9IDBcbmV4cG9ydCB7IGJhciB9XG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

## [no-useless-backreference]
🔖 [#12690]

正規表現中の無意味な後方参照を禁止するルールが追加されました。

```js:例
/*eslint no-useless-backreference: error */

//✘ BAD
let a = /foo\1(bar)/
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tdXNlbGVzcy1iYWNrcmVmZXJlbmNlOiBlcnJvciAqL1xuXG4vL+KcmCBCQURcbmxldCBhID0gL2Zvb1xcMShiYXIpL1xuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo4LCJzb3VyY2VUeXBlIjoibW9kdWxlIiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7fSwiZW52Ijp7fX19)

# 🔧 オプションが追加されたルール

## [array-callback-return]: `checkForEach`
🔖 [#12646]

`forEach()`メソッドのコールバックについても`return`文をチェックするオプションが追加されました。

```js:例
/*eslint array-callback-return: [error, { checkForEach: true }] */

//✘ BAD
list.forEach(x => {
    return x * 2
})
list.forEach(x => x * 2)

//✔ GOOD
list.forEach(x => {
    x * 2
})
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgYXJyYXktY2FsbGJhY2stcmV0dXJuOiBbZXJyb3IsIHsgY2hlY2tGb3JFYWNoOiB0cnVlIH1dICovXG5cbi8v4pyYIEJBRFxubGlzdC5mb3JFYWNoKHggPT4ge1xuICAgIHJldHVybiB4ICogMlxufSlcbmxpc3QuZm9yRWFjaCh4ID0+IHggKiAyKVxuXG4vL+KclCBHT09EXG5saXN0LmZvckVhY2goeCA9PiB7XG4gICAgeCAqIDJcbn0pXG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

## [array-element-newline]: `ArrayExpression` and `ArrayPattern`
🔖 [#11796]

配列リテラルと分割代入の配列パターンとで別々の設定を行うためのオプションが追加されました。

```js:例
/*eslint array-element-newline: [error, { ArrayExpression: always, ArrayPattern: never }] */

//✘ BAD
let foo = [1, 2]
let [
    a,
    b
] = foo
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgYXJyYXktZWxlbWVudC1uZXdsaW5lOiBbZXJyb3IsIHsgQXJyYXlFeHByZXNzaW9uOiBhbHdheXMsIEFycmF5UGF0dGVybjogbmV2ZXIgfV0gKi9cblxuLy/inJggQkFEXG5sZXQgZm9vID0gWzEsIDJdXG5sZXQgW1xuICAgIGEsXG4gICAgYlxuXSA9IGZvb1xuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo4LCJzb3VyY2VUeXBlIjoibW9kdWxlIiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7fSwiZW52Ijp7fX19)

## [indent]: `offsetTernaryExpressions` 
🔖 [#12556]

三項演算子の2項目と3項目のインデントをつけるオプションが追加されました。

```js:例
/*eslint indent: [error, 4, { offsetTernaryExpressions: true }] */

//✘ BAD
let foo = cond
    ? () => {
        doSomething()
    }
    : () => {
        doSomething()
    }

//✔ GOOD
let bar = cond
    ? () => {
            doSomething()
        }
    : () => {
            doSomething()
        }
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgaW5kZW50OiBbZXJyb3IsIDQsIHsgb2Zmc2V0VGVybmFyeUV4cHJlc3Npb25zOiB0cnVlIH1dICovXG5cbi8v4pyYIEJBRFxubGV0IGZvbyA9IGNvbmRcbiAgICA/ICgpID0+IHtcbiAgICAgICAgZG9Tb21ldGhpbmcoKVxuICAgIH1cbiAgICA6ICgpID0+IHtcbiAgICAgICAgZG9Tb21ldGhpbmcoKVxuICAgIH1cblxuLy/inJQgR09PRFxubGV0IGJhciA9IGNvbmRcbiAgICA/ICgpID0+IHtcbiAgICAgICAgICAgIGRvU29tZXRoaW5nKClcbiAgICAgICAgfVxuICAgIDogKCkgPT4ge1xuICAgICAgICAgICAgZG9Tb21ldGhpbmcoKVxuICAgICAgICB9XG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

## [indent]: `outerIIFEBody:"off"` 
🔖 [#12706]

トップレベルの即時関数呼び出しのインデントを検証しないオプションが追加されました。

```js:例
/*eslint indent: [error, 4, { outerIIFEBody: "off" }]*/

//✔ GOOD
(function() {

function foo(x) {
    return x + 1;
}

})();
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgaW5kZW50OiBbZXJyb3IsIDQsIHsgb3V0ZXJJSUZFQm9keTogXCJvZmZcIiB9XSovXG5cbi8v4pyUIEdPT0RcbihmdW5jdGlvbigpIHtcblxuZnVuY3Rpb24gZm9vKHgpIHtcbiAgICByZXR1cm4geCArIDE7XG59XG5cbn0pKCk7XG4iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjgsInNvdXJjZVR5cGUiOiJtb2R1bGUiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnt9LCJlbnYiOnt9fX0=)

## [no-extra-boolean-cast]: `enforceForLogicalOperands`
🔖 [#12734]

論理式のオペランドでも不要な明示的な `boolean` 型変換を禁止するオプションが追加されました。

```js:例
/*eslint no-extra-boolean-cast: [error, { enforceForLogicalOperands: true }] */

//✘ BAD
if (!!bar || Boolean(baz)) ;
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tZXh0cmEtYm9vbGVhbi1jYXN0OiBbZXJyb3IsIHsgZW5mb3JjZUZvckxvZ2ljYWxPcGVyYW5kczogdHJ1ZSB9XSAqL1xuXG4vL+KcmCBCQURcbmlmICghIWJhciB8fCBCb29sZWFuKGJheikpIDtcbiIsIm9wdGlvbnMiOnsicGFyc2VyT3B0aW9ucyI6eyJlY21hVmVyc2lvbiI6OCwic291cmNlVHlwZSI6Im1vZHVsZSIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==)

## [no-magic-numbers]: BigInt in the `ignore` option
🔖 [#12701]

`ignore`オプションが新たに文字列を受け入れるようになりました。各文字列は BigInt リテラルとして有効な文字列である必要があります。

```js:例
/*eslint no-magic-numbers: [error, { ignore: ["123n"] }] */

//✔ GOOD
if (foo === 123n) ;

//✘ BAD
if (foo === 456n) ;
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tbWFnaWMtbnVtYmVyczogW2Vycm9yLCB7IGlnbm9yZTogW1wiMTIzblwiXSB9XSAqL1xuXG4vL+KclCBHT09EXG5pZiAoZm9vID09PSAxMjNuKSA7XG5cbi8v4pyYIEJBRFxuaWYgKGZvbyA9PT0gNDU2bikgO1xuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjoxMSwic291cmNlVHlwZSI6Im1vZHVsZSIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==)

## [no-void]: `allowAsStatement`
🔖 [#12613]

式文の最初に書く`void`式を許可するオプションが追加されました。

```js:例
/*eslint no-void: [error, { allowAsStatement: true }] */

//✔ GOOD
void doSomething()
void (async () => {
    doSomething()
})().catch(handleError)

//✘ BAD
let a = void doSomething()
```

» [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyplc2xpbnQgbm8tdm9pZDogW2Vycm9yLCB7IGFsbG93QXNTdGF0ZW1lbnQ6IHRydWUgfV0gKi9cblxuLy/inJQgR09PRFxudm9pZCBkb1NvbWV0aGluZygpXG52b2lkIChhc3luYyAoKSA9PiB7XG4gICAgZG9Tb21ldGhpbmcoKVxufSkoKS5jYXRjaChoYW5kbGVFcnJvcilcblxuLy/inJggQkFEXG5sZXQgYSA9IHZvaWQgZG9Tb21ldGhpbmcoKVxuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjoxMSwic291cmNlVHlwZSI6Im1vZHVsZSIsImVjbWFGZWF0dXJlcyI6e319LCJydWxlcyI6e30sImVudiI6e319fQ==)

----

[RFC020]: https://github.com/eslint/rfcs/blob/master/designs/2019-additional-lint-targets/README.md
[RFC025]: https://github.com/eslint/rfcs/blob/master/designs/2019-rule-tester-improvements/README.md
[RFC032]: https://github.com/eslint/rfcs/blob/master/designs/2019-deprecating-personal-config/README.md
[RFC033]: https://github.com/eslint/rfcs/blob/master/designs/2019-description-in-directive-comments/README.md
[RFC037]: https://github.com/eslint/rfcs/blob/master/designs/2019-changing-base-path-in-config-files-that-cli-options-specify/README.md
[RFC040]: https://github.com/eslint/rfcs/blob/master/designs/2019-move-to-async-api/README.md
[RFC044]: https://github.com/eslint/rfcs/blob/master/designs/2019-drop-node8/README.md
[RFC047]: https://github.com/eslint/rfcs/blob/master/designs/2019-plugin-loading-improvement/README.md
[RFC051]: https://github.com/eslint/rfcs/blob/master/designs/2019-update-default-ignore-patterns/README.md

[#11796]: https://github.com/eslint/eslint/pull/11796
[#12096]: https://github.com/eslint/eslint/pull/12096
[#12195]: https://github.com/eslint/eslint/pull/12195
[#12490]: https://github.com/eslint/eslint/pull/12490
[#12546]: https://github.com/eslint/eslint/pull/12546
[#12556]: https://github.com/eslint/eslint/pull/12556
[#12608]: https://github.com/eslint/eslint/pull/12608
[#12613]: https://github.com/eslint/eslint/pull/12613
[#12635]: https://github.com/eslint/eslint/pull/12635
[#12646]: https://github.com/eslint/eslint/pull/12646
[#12668]: https://github.com/eslint/eslint/pull/12668
[#12677]: https://github.com/eslint/eslint/pull/12677
[#12678]: https://github.com/eslint/eslint/pull/12678
[#12690]: https://github.com/eslint/eslint/pull/12690
[#12699]: https://github.com/eslint/eslint/pull/12699
[#12700]: https://github.com/eslint/eslint/pull/12700
[#12701]: https://github.com/eslint/eslint/pull/12701
[#12706]: https://github.com/eslint/eslint/pull/12706
[#12734]: https://github.com/eslint/eslint/pull/12734
[#12757]: https://github.com/eslint/eslint/pull/12757
[#12765]: https://github.com/eslint/eslint/pull/12765
[#12806]: https://github.com/eslint/eslint/pull/12806
[#12816]: https://github.com/eslint/eslint/pull/12816
[#12837]: https://github.com/eslint/eslint/pull/12837
[#12876]: https://github.com/eslint/eslint/pull/12876
[#12887]: https://github.com/eslint/eslint/pull/12887
[#12888]: https://github.com/eslint/eslint/pull/12888
[#12898]: https://github.com/eslint/eslint/pull/12898
[#12913]: https://github.com/eslint/eslint/pull/12913
[#12915]: https://github.com/eslint/eslint/pull/12915
[#12919]: https://github.com/eslint/eslint/pull/12919
[#12920]: https://github.com/eslint/eslint/pull/12920
[#12922]: https://github.com/eslint/eslint/pull/12922
[#12927]: https://github.com/eslint/eslint/pull/12927
[#12939]: https://github.com/eslint/eslint/pull/12939
[#12955]: https://github.com/eslint/eslint/pull/12955

[accessor-pairs]: https://eslint.org/docs/rules/accessor-pairs
[array-callback-return]: https://eslint.org/docs/rules/array-callback-return
[array-element-newline]: https://eslint.org/docs/rules/array-element-newline
[callback-return]: https://eslint.org/docs/rules/callback-return
[computed-property-spacing]: https://eslint.org/docs/rules/computed-property-spacing
[default-case-last]: https://eslint.org/docs/rules/default-case-last
[func-names]: https://eslint.org/docs/rules/func-names
[global-require]: https://eslint.org/docs/rules/global-require
[handle-callback-err]: https://eslint.org/docs/rules/handle-callback-err
[indent]: https://eslint.org/docs/rules/indent
[no-constant-condition]: https://eslint.org/docs/rules/no-constant-condition
[no-dupe-class-members]: https://eslint.org/docs/rules/no-dupe-class-members
[no-dupe-else-if]: https://eslint.org/docs/rules/no-dupe-else-if
[no-extra-boolean-cast]: https://eslint.org/docs/rules/no-extra-boolean-cast
[no-extra-parens]: https://eslint.org/docs/rules/no-extra-parens
[no-implied-eval]: https://eslint.org/docs/rules/no-implied-eval
[no-import-assign]: https://eslint.org/docs/rules/no-import-assign
[no-iterator]: https://eslint.org/docs/rules/no-iterator
[no-magic-numbers]: https://eslint.org/docs/rules/no-magic-numbers
[no-mixed-requires]: https://eslint.org/docs/rules/no-mixed-requires
[no-new-require]: https://eslint.org/docs/rules/no-new-require
[no-path-concat]: https://eslint.org/docs/rules/no-path-concat
[no-process-env]: https://eslint.org/docs/rules/no-process-env
[no-process-exit]: https://eslint.org/docs/rules/no-process-exit
[no-restricted-exports]: https://eslint.org/docs/rules/no-restricted-exports
[no-restricted-modules]: https://eslint.org/docs/rules/no-restricted-modules
[no-proto]: https://eslint.org/docs/rules/no-proto
[no-setter-return]: https://eslint.org/docs/rules/no-setter-return
[no-sync]: https://eslint.org/docs/rules/no-sync
[no-useless-backreference]: https://eslint.org/docs/rules/no-useless-backreference
[no-void]: https://eslint.org/docs/rules/no-void
[quote-props]: https://eslint.org/docs/rules/quote-props
[radix]: https://eslint.org/docs/rules/radix
[use-isnan]: https://eslint.org/docs/rules/use-isnan
[yoda]: https://eslint.org/docs/rules/yoda

[eslint-plugin-node]: https://github.com/mysticatea/eslint-plugin-node
[node/callback-return]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/callback-return.md
[node/global-require]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/global-require.md
[node/handle-callback-err]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/handle-callback-err.md
[node/no-mixed-requires]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-mixed-requires.md
[node/no-new-require]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-new-require.md
[node/no-path-concat]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-path-concat.md
[node/no-process-env]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-process-env.md
[node/no-process-exit]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-process-exit.md
[node/no-restricted-import]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-restricted-import.md
[node/no-restricted-require]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-restricted-require.md
[node/no-sync]: https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-sync.md

[--config]: https://eslint.org/docs/user-guide/command-line-interface#c-config
[--ignore-path]: https://eslint.org/docs/user-guide/command-line-interface#ignore-path
[--resolve-plugins-relative-to]: https://eslint.org/docs/user-guide/command-line-interface#resolve-plugins-relative-to
[CLIEngine]: https://eslint.org/docs/developer-guide/nodejs-api#cliengine
[ESLint]: https://eslint.org/docs/developer-guide/nodejs-api#eslint-class
[RuleTester]: https://eslint.org/docs/developer-guide/nodejs-api#eslint-class
[overrides]: https://eslint.org/docs/user-guide/configuring#configuration-based-on-glob-patterns