ESLint v4.0.0 の変更点まとめ

前 [v3.19.0] | 次 [v4.1.0]

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">We&#39;re excited to announce that ESLint v4.0.0 has been released! <a href="https://t.co/sLe0kCwfMA">https://t.co/sLe0kCwfMA</a></p>&mdash; ESLint (@geteslint) <a href="https://twitter.com/geteslint/status/874081043522887680">2017年6月12日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

ESLint 4.0.0 がリリースされました!

主にはインデント ルールの改定、公開 API のクラス化、コメント関連の API 変更などです。エンドユーザー向けには特にインデント ルールの改定の影響が大きいでしょう。それ以外は見えないところが変わった感じだと思います。

- [Release note: 4.0.0-alpha.0](http://eslint.org/blog/2017/04/eslint-v4.0.0-alpha.0-released)
- [Release note: 4.0.0-alpha.1](http://eslint.org/blog/2017/04/eslint-v4.0.0-alpha.1-released)
- [Release note: 4.0.0-alpha.2](http://eslint.org/blog/2017/05/eslint-v4.0.0-alpha.2-released)
- [Release note: 4.0.0-beta.0](http://eslint.org/blog/2017/05/eslint-v4.0.0-beta.0-released)
- [Release note: 4.0.0-rc.0](http://eslint.org/blog/2017/06/eslint-v4.0.0-rc.0-released)
- [Release note: 4.0.0](http://eslint.org/blog/2017/06/eslint-v4.0.0-released)
- [Migrating to v4.0.0](http://eslint.org/docs/4.0.0/user-guide/migrating-to-4.0.0)

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

- :globe_with_meridians: [日本語 Issue 管理リポジトリ](https://github.com/eslint/eslint-jp)
- :speech_balloon: [日本語サポート チャット](https://gitter.im/eslint/eslint-jp)
- :globe_with_meridians: [本家リポジトリ](https://github.com/eslint/eslint)
- :speech_balloon: [本家サポート チャット](https://gitter.im/eslint/eslint)

----

# ⚠️ 非互換な変更 (ユーザー向け)

## [#8236], [#8239]: `eslint:recommended`が変更されます

- [no-compare-neg-zero] ルールが有効になります。
- [no-useless-escape] ルールが有効になります。

## [#7618]: [indent] ルールが変更されます

より厳しいインデント チェックが行われるようになります。
例えば、既存では無視されていたコメント行や式の途中の行、閉じカッコの行などがチェックされるようになります。

> もし[indent]ルールの振る舞いをもとに戻したい場合、代わりに[indent-legacy]ルールをご利用ください。
>
> ```json
> {
>     "rules": {
>         "indent": "off",
>         "indent-legacy": ["error", /* your configuration */]
>     }
> }
> ```

## [#8213]: `.eslintrc`ファイルのエラーチェックが強化されます

設定ファイルが無効なプロパティを持つ場合、ESLint がエラーを投げるようになります。
例えば、スペルミスや ESLint 0.x の頃に書いた古い設定が残っていた場合などにエラーになります。

## [#6759]: `.eslintignore`ファイルの振る舞いが変更されます

`.eslintignore`に書かれたパスの解決方法が変わります。
従来はカレント ディレクトリを起点にパスを解決していましたが、4.0.0 からは`.eslintignore`ファイルの位置を起点に解決されます。

ESLint は通常カレント ディレクトリにある`.eslintignore`ファイルを利用するので、大半のケースでは違いがありません。ただし、CLIオプションによって別の場所にある`.eslintignore`ファイルを指定している場合に影響を受けます。

## [#7693], [#7879], [#8267]: いくつかのルールのデフォルトの振る舞いが変更されます

- [no-multi-spaces] ... コードと末尾コメントの間の空白をチェックするようになります。
- [padded-blocks] ... Switch 文と Class 定義をチェックするようになります。
- [space-before-function-paren] ... Async アロー関数の`async`キーワードと引数カッコの間の空白をチェックするようになります。

## [#6362]: [npm scoped packages] によるプラグインの指定方法が変更されます

[あのときのあれ](http://qiita.com/mysticatea/items/4fe399cf0a1d675b6172#6362-scoped-%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AB%E3%82%88%E3%82%8B%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%8C%E5%AE%9A%E7%BE%A9%E3%81%99%E3%82%8B%E3%83%AB%E3%83%BC%E3%83%AB%E3%81%AE%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95%E3%81%8C%E5%A4%89%E6%9B%B4%E3%81%95%E3%82%8C%E3%81%9F)です。

従来の [npm scoped packages] によるプラグインのルールは、次のように指定していました。

```json
{
    "plugins": [
        "@my-organization/foo"
    ],
    "rules": {
        "foo/some-rule": "error"
    }
}
```

しかし`foo/some-rule`だと、`eslint-plugin-foo`のルールなのか`@my-organization/foo`のルールなのか区別がつかないため、指定方法が変更されます。

```json
{
    "plugins": [
        "@my-organization/foo"
    ],
    "rules": {
        "@my-organization/foo/some-rule": "error"
    }
}
```

# ⚠️ 非互換な変更 (プラグイン/独自ルール開発者向け)

## [#8213]: `RuleTester`のテストパターン チェックが強化されます

テストパターンが無効なプロパティを持っていた場合にエラーが出力されるようになります。
これにより、テストしていたつもりが実はスペルミスで... というのを検出できるようになります。

## [#6724]: AST nodes からコメントのプロパティが削除されます

各 AST ノードから非標準の`leadingComments`/`trailingComments`プロパティが削除されます。
代わりにコメント取得の公開 API をご利用ください。

- `node.leadingComments` → `sourceCode.getCommentsBefore(node)`
- `node.trailingComments` → `sourceCode.getCommentsAfter(node)`

また、コメント アタッチメントの処理が`espree`から`eslint`に移動されたため、パーサー プラグインを作る労力が減ります。

## [#6724]: コメント取得 API が Shebang を (正式に) 含むようになります

これまで、実装のバグにより、一部のコメント取得 API は Shebang を1行コメントの1つとして返していました。
4.0.0 から、すべてのコメント取得 API が Shebang を含むようになります。このとき、コメント種別は `type: "Shebang"` となります。

## [#8408]: コメント取得 API が変更されます

これまで `sourceCode.getComments(node)` を提供していましたが、これは非推奨になります。
代わりに以下の3種類のメソッドをご利用ください。

- `sourceCode.getCommentsBefore(node)`
- `sourceCode.getCommentsAfter(node)`
- `sourceCode.getCommentsInside(node)`

# ⚠️ 非互換な変更 (連携ツール開発者向け)

## [#8295]: `linter.verify()` API のオプションから `global` プロパティが削除されます

これまで `linter.verify()` API は、オプションの1つとして `global` プロパティを受け付けていました (これは `globals` プロパティの別名です)。
しかし、4.0.0 から `global` プロパティを認識しなくなります。

## [#8004]: より多くのルールの Lint 結果が `endLine`/`endColumn` を持つようになります

Lint 結果の`endLine`/`endColumn`プロパティは、主にエディタ連携でエラー箇所に赤線を引くために利用されています。これらプロパティは比較的最近で追加されたもので、(互換性のために) ルールが特別に指定しない限りは`undefined`になっていました。

4.0.0 から、ルールが報告した AST ノードの範囲に従って`endLine`/`endColumn`プロパティが生成されるようになります。`Program`ノード、`FunctionDeclaration`ノードなど、広い範囲の AST ノードを報告するルールは修正する必要があるかもしれません。

## [#8231]: 公開 API のいくつかが ES2015 クラスになります

`CLIEngine`, `SourceCode`, `RuleContext`等の API がクラスになります。
そのため、`new`抜きのコンストラクタ呼び出しがエラーになったり、メソッドが`for-in`文などで列挙されなくなったりします。

## [#7364]: Lint 結果が Fixable なエラー・警告の数を持つようになります

Lint 結果が新しいプロパティ`fixableErrorCount`と`fixableWarningCount`を持つようになります。
これらは、報告されたエラー・警告のうち、`eslint --fix`コマンドで修正できるものの数です。

## [#8454]: `linter` オブジェクトが非推奨になり、代わりに `Linter` クラスが追加されます

今まで API としてシングルトンの `linter` オブジェクトが公開されていましたが、これは非推奨になります。
代わりに `Linter` コンストラクタが追加されました。

```js
const eslint = require("eslint")

// 従来は linter オブジェクトを使っていた
eslint.linter.defineRule("foo", foo)
eslint.linter.verify(text, config)

// 4.0.0 以降は Linter コンストラクタを使う
const linter = new eslint.Linter()
linter.defineRule("foo", foo)
linter.verify(text, config)
```

同一プロセス内で複数の `CLIEngine` を初期化したときに、内部的に `linter` の状態を共有してしまうのが問題になっていたため、この変更が行われました。


# 💡 新しいルール

## [#5614]: [no-buffer-constructor]

Node.js 6 にて非推奨になった`Buffer`コンストラクタを警告するルールです。
代わりに`Buffer.alloc`と`Buffer.from`をご利用ください。

なお、`Buffer.alloc`と`Buffer.from`は Node.js 4.5.0 で追加された関数なので、それ以前のバージョンをサポートする場合は Feross の [safe-buffer] モジュールを利用する必要があります。

```js
/*eslint no-buffer-constructor: error */

//✘ BAD
let a = new Buffer(10)
let b = new Buffer("hello")

//✔ GOOD
let a = Buffer.alloc(10)
let b = Buffer.from("hello")
```

蛇足ですが、その他の非推奨になっているものを警告したい場合は [eslint-plugin-node] の [node/no-deprecated-api] ルールを利用できます。今回`Buffer`コンストラクタだけコアルールになったのは、それがセキュリティ Issue で重要だからのようです。

## [#6073]: [array-bracket-newline]

![JSCS Icon](http://jscs.info/favicon.ico) JSCS 互換ルールです。

配列リテラルのカッコの内側の改行に関するスタイルを矯正するスタイル・ルールです。

いくつかオプションがあり、中身が複数行の場合に改行を必須としたり、要素数に応じて改行あり・なしを切り替えたりできます。

```js
/*eslint array-bracket-newline: [error, {minItems: 3}] */

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

//✔ GOOD
let a = [
    1, 2, 3,
]
let b = [1, 2]
```

> 要素の間の改行は次項 [array-element-newline] を利用する。

## [#6075]: [array-element-newline]

![JSCS Icon](http://jscs.info/favicon.ico) JSCS 互換ルールです。

配列リテラルの各要素間の改行スタイルを矯正するスタイル・ルールです。

いくつかオプションがあり、中身が複数行の場合に改行を必須としたり、要素数に応じて改行あり・なしを切り替えたりできます。

```js
/*eslint array-element-newline: [error, {minItems: 3}] */

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

//✔ GOOD
let a = [1,
    2,
    3]
let b = [1, 2]
```

> カッコと要素の間の改行は前項 [array-bracket-newline] を利用する。

## [#7356]: [padding-line-between-statements]

2つの文の間に空白行を置くべきかどうかを指定するスタイル・ルールです。
今まで数種類の "特定の文の前後に空白行を置くべきかを指定するスタイル・ルール" がありましたが、それらは非推奨になり、このルールに一本化されました。

ルールは「空白行の要不要 (`never` or `always`) と2種類の文の種別」を1セットにして、そのセットを任意の数だけ設定できます。

例えば「`return`文の前に空白行が常に必要」にする場合は次のようになります。

```js
/*eslint padding-line-between-statements: [
    "error",
    { blankLine: "always", prev: "*", next: "return" }
] */

//✘ BAD
function foo() {
    bar();
    return;
}

//✔ GOOD
function foo() {
    bar();

    return;
}
function foo() {
    return;
}
```

例えば「`return`文の前に空白行が常に必要」かつ「関数定義の前後には空白行が常に必要」にする場合は次のようになります。

```js
/*eslint padding-line-between-statements: [
    "error",
    { blankLine: "always", prev: "*", next: "return" },
    { blankLine: "always", prev: "function", next: "*" },
    { blankLine: "always", prev: "*", next: "function" }
] */

//✘ BAD
function foo() {
    bar();
    return;
}
function foo() {
}

//✔ GOOD
function foo() {
    bar();

    return;
}

function foo() {
}
```

設定は後優先です。
複数の設定にマッチする場合は、一番最後の設定が有効になります。

例えば「変数宣言の後には空白行が常に必要」だが「変数宣言同士の間には空白行を許可しない」にする場合は次のようになります。

```js
/*eslint padding-line-between-statements: [
    "error",
    { blankLine: "always", prev: ["const", "let", "var"], next: "*" },
    { blankLine: "never", prev: ["const", "let", "var"], next: ["const", "let", "var"] }
] */

//✘ BAD
var a;

var b;
foo()

//✔ GOOD
var a;
var b;

foo()
```

## [#7981]: [switch-colon-spacing]

`switch`文の`case`/`default`句にあるコロン`:`の前後の空白に関するスタイル・ルールです。
デフォルトでは、コロンの前には空白を許可せず、コロンの後には空白か改行を必要とします。

```js
/*eslint switch-colon-spacing: error */

//✘ BAD
switch (a) {
    case 0 :foo(); break;
    case 1:bar(); break;
    default : baz(); break;
}

//✔ GOOD
switch (a) {
    case 0: foo(); break;
    case 1:
        bar();
        break;
    default:
        baz();
        break;
}
```

## [#8169]: [semi-style]

セミコロンを行頭に置くか、行末に置くかを指定するスタイル・ルールです。

```js
/*eslint semi-style: [error, last] */

//✘ BAD
foo()
;[1, 2, 3].forEach(foo)

//✔ GOOD
foo();
[1, 2, 3].forEach(foo)
```

## [#8387]: [for-direction]

`for`文の比較の方向と更新の方向が食い違っていた場合に警告するルールです。

```js
/*eslint for-direction: error */

//✘ BAD
for (let i = 0; i < 10; --i) {
}
for (let i = 10; i >= 0; ++i) {
}

//✔ GOOD
for (let i = 0; i < 10; ++i) {
}
for (let i = 10; i >= 0; --i) {
}
```

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

## [#6488]: [object-curly-newline] consistent

オブジェクト リテラルのカッコの内側の改行に関して、"改行禁止" の警告を抑制するオプションが追加されました。

```js
/*eslint object-curly-newline: [error, {minItems: 2, consistent: true}]*/

//✔ GOOD
let a = {
    foo: 1
}
```

# ✒️ `eslint --fix` をサポートしたルール

## [#8347]: [no-confusing-arrow]

```js
/*eslint no-confusing-arrow: [error, {allowParens: true}] */

a => 1 ? 2 : 3

// gets fixed to:

a => (1 ? 2 : 3)
```

## [#8660]: [no-debugger]

```js
/*eslint no-debugger: error */

foo()
debugger
bar()

// gets fixed to:

foo()

bar()
```

# ❌ 非推奨になったルール

## [#8099]: [newline-after-vars]

[padding-line-between-statements] ルールで置き換えられました。

## [#8099]: [newline-before-return]

[padding-line-between-statements] ルールで置き換えられました。

## [#8099]: [lines-around-directive]

[padding-line-between-statements] ルールで置き換えられました。

----

[v3.19.0]: http://qiita.com/mysticatea/items/172be6510b91c36711f4
[v4.1.0]: http://qiita.com/mysticatea/items/e758c9a9a7dfb8b9cdb1
[#5614]: https://github.com/eslint/eslint/issues/5614
[#6073]: https://github.com/eslint/eslint/issues/6073
[#6075]: https://github.com/eslint/eslint/issues/6075
[#6362]: https://github.com/eslint/eslint/issues/6362
[#6488]: https://github.com/eslint/eslint/issues/6488
[#6724]: https://github.com/eslint/eslint/issues/6724
[#6759]: https://github.com/eslint/eslint/issues/6759
[#7129]: https://github.com/eslint/eslint/issues/7129
[#7356]: https://github.com/eslint/eslint/issues/7356
[#7364]: https://github.com/eslint/eslint/issues/7364
[#7618]: https://github.com/eslint/eslint/issues/7618
[#7693]: https://github.com/eslint/eslint/issues/7693
[#7879]: https://github.com/eslint/eslint/issues/7879
[#7981]: https://github.com/eslint/eslint/issues/7981
[#8004]: https://github.com/eslint/eslint/issues/8004
[#8099]: https://github.com/eslint/eslint/issues/8099
[#8169]: https://github.com/eslint/eslint/issues/8169
[#8213]: https://github.com/eslint/eslint/issues/8213
[#8231]: https://github.com/eslint/eslint/issues/8231
[#8236]: https://github.com/eslint/eslint/issues/8236
[#8239]: https://github.com/eslint/eslint/issues/8239
[#8267]: https://github.com/eslint/eslint/issues/8267
[#8295]: https://github.com/eslint/eslint/issues/8295
[#8347]: https://github.com/eslint/eslint/issues/8347
[#8387]: https://github.com/eslint/eslint/issues/8387
[#8408]: https://github.com/eslint/eslint/issues/8408
[#8454]: https://github.com/eslint/eslint/issues/8454
[#8660]: https://github.com/eslint/eslint/issues/8660
[#9999]: https://github.com/eslint/eslint/issues/9999
[array-bracket-newline]: http://eslint.org/docs/4.0.0/rules/array-bracket-newline
[array-element-newline]: http://eslint.org/docs/4.0.0/rules/array-element-newline
[for-direction]: http://eslint.org/docs/4.0.0/rules/for-direction
[indent]: http://eslint.org/docs/4.0.0/rules/indent
[indent-legacy]: http://eslint.org/docs/4.0.0/rules/indent-legacy
[newline-after-vars]: http://eslint.org/docs/rules/newline-after-vars
[lines-around-directive]: http://eslint.org/docs/rules/lines-around-directive
[newline-before-return]: http://eslint.org/docs/rules/newline-before-return
[no-buffer-constructor]: http://eslint.org/docs/4.0.0/rules/no-buffer-constructor
[no-compare-neg-zero]: http://eslint.org/docs/rules/no-compare-neg-zero
[no-confusing-arrow]: http://eslint.org/docs/rules/no-confusing-arrow
[no-debugger]: http://eslint.org/docs/rules/no-debugger
[no-multi-spaces]: http://eslint.org/docs/rules/no-multi-spaces
[no-useless-escape]: http://eslint.org/docs/rules/no-useless-escape
[object-curly-newline]: http://eslint.org/docs/rules/object-curly-newline
[padded-blocks]: http://eslint.org/docs/rules/padded-blocks
[padding-line-between-statements]: http://eslint.org/docs/4.0.0/rules/padding-line-between-statements
[semi-style]: http://eslint.org/docs/rules/semi-style
[space-before-function-paren]: http://eslint.org/docs/rules/space-before-function-paren
[switch-colon-spacing]: http://eslint.org/docs/rules/switch-colon-spacing
[xxxx]: http://eslint.org/docs/rules/xxxx

[safe-buffer]: https://www.npmjs.com/package/safe-buffer
[eslint-plugin-node]: https://github.com/mysticatea/eslint-plugin-node#readme
[node/no-deprecated-api]: https://github.com/mysticatea/eslint-plugin-node/blob/f1a137b1250cd457cd9dfdf0bf851d1efa0ce2fa/docs/rules/no-deprecated-api.md
[npm scoped packages]: https://docs.npmjs.com/misc/scope

<!-- 
![JSCS Icon](http://jscs.info/favicon.ico) JSCS 互換ルールです。
-->