ESLint v2.0.0 の変更点まとめ

  • 81
    Like
  • 0
    Comment
More than 1 year has passed since last update.

前 - | 次 v2.1.0

ESLint v2.0.0 の変更点をまとめました。

  • 前半に利用者向けの変更内容を、後半にプラグイン開発者向けの変更内容を記載しています。
  • 単純なバグ修正は記載していません。
  • 一覧したい場合は、右列のTOCをご利用ください。

公式情報:

ピックアップ - 利用者に影響が大きそうな Breaking Changes:

ピックアップ - プラグイン開発者に影響が大きそうな Breaking Changes:

利用者向け

新機能 - New Features

.eslintrc自動生成機能 (#3567)

既存のプロジェクトに ESLint を導入する場合、既存プロジェクトに合わせた構成を作るのは大変です。そのため、Twitter では数千、数万の警告がなされたことを報告するツイートをよく見ます。この新機能は、既存のソースコードを元にして最適な.eslintrcを生成することを目的として作られました。

作者による解説記事

この機能は、.eslintrcを作成する既存機能である eslint --init コマンドから派生します。

shell
 $ eslint --init
 ? How would you like to configure ESLint?  # どのようにして設定しますか?
   Answer questions about your style        # 質問に答える
   Use a popular style guide                # 人気のスタイルから選択する
+  Inspect your JavaScript file(s)          # 既存のソースコードを解析する ← NEW!

※ 2.0.0 時点では、JSXなどの一部の構文が扱えません。このバグは近いうちに修正される予定です (#5007)。

--print-config CLI オプションが追加された (#5099)

.eslintrcはカスケード機能があり、あるフォルダ A とその親フォルダの両方に.eslintrcがある場合、それらが合成されます。
この--print-configを使うことで、指定したファイルに対して使用される合成後の設定を確認できます。

$ eslint --pring-config lib/foo/bar.js

• 新しいルール

  • no-whitespace-before-property (#1086) - foo.barのようなプロパティアクセスにて、ドットの前後にスペースがあったら警告するスタイル・ルールです。
  • array-callback-return (#1128) - Array.prototype.filterのような配列のメソッドについて、コールバック関数が正しくreturnしていなかった場合に警告します。新機能の実行パス解析を利用したルールです。
  • one-var-declaration-per-line (#1622) - var foo, bar, bazのような1行に多数の変数宣言を詰め込む書き方を警告するスタイル・ルールです。
  • sort-imports (#3143) - ES2015(ES6) モジュール構文において、Imports 宣言がアルファベット順に並んでいなかった場合に警告するスタイル・ルールです。これに似ているルールに sort-vars があります。
  • no-restricted-imports (#3196) - ES2015(ES6) モジュール構文において、利用禁止するモジュールを指定できるルールです。似ているルールにno-restricted-modulesがあり、こちらはrequire関数で利用禁止するモジュールを指定できます。
  • id-blacklist (#3358) - 変数名として利用できない文字列のリストを指定できるルールです。
  • keyword-spacing (#3861) - キーワードの前後の空白を矯正するスタイル・ルールです。ESLint v1 に存在した space-after-keywords, space-before-keywords, space-return-throw-case の3つのルールを統合しました。
  • prefer-rest-params (#4108) - arguments変数の利用を禁止するルールです。代わりに ES2015 で追加された Rest Parameters 構文を使いましょう。
  • yield-star-spacing (#4115) - yield*構文の*の前後のスペースを矯正するスタイル・ルールです。
  • no-confusing-arrow (#4417) - 削除されたno-arrow-conditionルールのうち、no-constant-conditionルールがカバーしない部分を抽出したルールです。list.map(x => x ? 1 : 2)のようなコードが警告されます。
  • no-unmodified-loop-condition (#4523) - whilefor文の条件式に、ループ内で変更されない変数が使われていた場合に警告するルールです。
  • newline-per-chained-call (#4538) - 1行の中に連続したメソッド・チェーンがあると警告するルールです。
  • no-implicit-globals (#4542) - 暗黙的にグローバル名前空間を汚染すると警告するルールです。基本的にはグローバル変数・関数宣言が警告されます。
  • no-self-assign (#4729) - 自己代入を警告するルールです。foo = foo;[a, b] = [a, x];のようなコードが警告されます。
  • no-useless-constructor (#4785) - Class 構文にて、コンストラクタ省略時と同じ動作しかしないコンストラクタを警告するルールです。それは単に削除できます。
  • template-curly-spacing (#5049) - Template Listerals 構文に式を埋め込むときに利用するカッコ(${...}) の内側のスペースを矯正するスタイル・ルールです。
  • no-unused-labels (#5052) - 未使用のラベルを警告するルールです。no-unused-vars のラベル版です。
  • no-extra-label (#5059) - 不要なラベルを警告するルールです。ループ構文やswitch構文の直下にあるbreak/continue文のラベルが警告されます。
  • no-empty-function (#5161) - 空の関数を警告するルールです。本文になんの文もコメントもない関数が警告されます。

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

  • valid-jsdoc (#3056) - JSDoc コメントの型指定において、{String}{string}のような、同じ型を意図する記述をどちらかに統一するためのオプションが追加されました。例えば「{String}を警告して{string}に統一する」といった風です。
  • strict (#3306) - "use strict";について、Node.js のような暗黙的に関数でラップされる環境ではグローバルに、それ以外の環境では関数内に書くべきだと指定するオプションが追加されました。同じ共有設定で、Node.js ではグローバルに、ブラウザでは関数内に"use strict";を書きたいというのが目的のようです。
  • no-implicit-coercion (#3308) - 指定した演算子を許可するallowオプションが追加されました。boolean型の暗黙変換として!!~x.indexOf(y)がセットになってたのが不評だったようで、!!だけ許可したいという要望が多かったです。
  • no-extra-parens (#3317) - while ((foo = bar())) { ... }のような、意図的な代入式であることを表すための余分なカッコを許可するオプションが追加されました。このようなカッコは古くからの習慣ですね。
  • no-underscore-dangle (#3435) - this._foo のような this に続くアンダースコアを許可するオプションが追加されました。obj._foo のようなものは警告されるため、擬似的なアクセス制御になります。
  • space-before-blocks (#4089) - Class Body の開きカッコの直前にスペースを書くかどうかを個別に設定するためのオプションが追加されました。
  • no-use-before-define (#4280) - 定義より前の位置でクラスを利用することを許可するオプションが追加されました。ただし、クラス定義は巻き上げないため、このオプションを利用するとエラーを取り逃す可能性があります。
  • operator-linebreak (#4294) - 特定の演算子だけ無視するオプションが追加されました。特に三項演算子は他の演算子と改行の仕方を変えることが多いため重宝しそうです。
  • max-statements (#4309) - トップレベルの IIFE だけ無視するオプションが追加されました。
  • no-magic-numbers (#4370) - 配列の添字を無視するオプションが追加されました。
  • semi (#4385) - 1-liner を書くときにブロックの閉じカッコの直前だけセミコロンを省略するスタイルを指定できるようになりました。
  • no-eval (#4441) - 間接的なeval呼び出しを許可するオプションが追加されました。間接的なeval呼び出しは、直接的なeval呼び出しと異なり呼び出し元のスコープを汚染せず、そのため呼び出し元の deoptimization の原因になりません。
  • object-shorthand (#4487) - 大文字で始まるメソッド (var obj = { Foo: function() { }) を無視するオプションが追加されました。メソッド省略記法は、通常の関数と異なりコンストラクタとして利用できないためです。
  • consistent-this (#4492) - 複数の候補を指定できるようになりました。
  • max-len (#4665) - コードとコメントで異なる文字数を指定できるようになりました。
  • key-spacing (#4697) - 単一行のオブジェクト定義と、複数行のオブジェクト定義とで別々の設定を行えるようになりました。
  • no-bitwise (#4742, #4873) - 特定の演算子だけ無視するオプションが追加されました。また、asm.js でint32型であることを示すヒント(|0)だけを許可するオプションが追加されました。
  • comma-dangle (#4967) - 複数行にわたる宣言でケツカンマを許可するオプションが追加されました。
  • no-labels (#5042) - ループ構文のラベルを許可するオプションと、switch構文のラベルを許可するオプションが追加されました。
  • no-multiple-empty-lines (#5045) - ファイル先頭の空行を警告するためのオプションが追加されました。
  • no-console (#5095) - 特定のメソッド (console.errorconsole.assert等) を許可するオプションが追加されました。

• 新しく Fixable になったルール

  • jsx-quotes (#4377) - JSX 属性を囲む "/' を矯正するスタイル・ルールです。
  • spaced-comment (#4969) - コメント先頭のスペースを矯正するスタイル・ルールです。
  • space-in-parens (#5050) - カッコ内のスペースを矯正するスタイル・ルールです。

• 新しい env

• 新しい ecmaFeatures

  • impliedStrict (#4832) - ソースコードを常に Strict Mode として扱うオプションです。事前コンパイル・ツールなどが自動的に "use strict" を付与する場合に使えます。

• 新しいフォーマッター

  • table (#4037) - テーブル状に Lint 結果を出力するフォーマッターです。
  • visualstudio (#4708) - Visual Studio が認識できる形式で Lint 結果を出力するフォーマッターです。

仕様変更 - Breaking Changes

• 削除された既存ルール

• 挙動が変わった既存ルール

  • space-before-blocks (#1338) - else { のような、キーワードとブロックの間にあるスペースを捕捉しなくなりました。space-after-keywordsルールと衝突していたためです。
  • consistent-return (#3373) - 値を返すreturn文が存在し、かつ値を返さない実行パスが存在する関数を警告するようになりました。例えば function foo(a) { if (a) { return true; } } この関数は従来は許可されていましたが、2.0.0では警告されます。
  • no-magic-numbers (#4193) - 従来は「例外的にマジック ナンバーとして扱わない数字」として、デフォルトで0, 1, 2が設定されていましたが、これが廃止されます。「例外的にマジック ナンバーとして扱わない数字」を指定したい場合、オプションで指定する必要があります。
  • prefer-const (#4474) - より多くのパターンを検出するようになりました。例えば let a; a = 0; のように宣言と初期化が分かれている場合、従来は許可されていました。2.0.0では警告されます。
  • eqeqeq (#4578) - --fix対応が廃止されました。fix周りはまだまだ仕様改善が必要です。
  • strict (#4961) - strictルールのオプションのデフォルト値が"safe"に変更されました。

bower_componentsが無視されるようになった (#3550)

ESLint はデフォルトでnode_modulesディレクトリを無視します。
2.0.0からは、加えてbower_componentsも無視されるようになります。

.eslintignoreファイルを作ることでこのふるまいを修正できます。

• ES2015(ES6) の新しいグローバル変数が削除された (#4085)

従来はPromiseMap等の ES2015(ES6) で追加されたグローバル変数が、デフォルトで存在するものとして扱われていました。
これは ES5 環境で開発している利用者にとって有害なので、削除されました。

2.0.0からは、env: {es6: true}を指定することで新しいグローバル変数が追加されます。

.eslintrc
{
    "env": {
        "es6": true
    }
}

package.json.eslintrcの合成が廃止された (#4451)

従来はpackage.json.eslintrcの両方に ESLint の設定が書かれていた場合は、それらの設定が合成されていました。
2.0.0からは、.eslintrcが存在しなかった場合だけpackage.json内の設定が使われます。

package.json内と.eslintrcの両方に設定を書いている場合、どちらかに統一する必要があります。

ecmaFeatures設定項目が廃止された (#4641)

ESLint で ES2015(ES6) の構文を利用するため、.eslintrcecmaFeaturesを記述している方もいると思います。この設定項目は、実は構文解析器(Parser)のための設定項目のひとつだったので、parserOptionsという名前に変更になります。また、従来は構文の種類ごとに設定できていたのができなくなります。

.eslintrc(従来)
{
    "ecmaFeatures": {
        "arrowFunctions": true,
        "binaryLiterals": true,
        "blockBindings": true,
        "classes": true,
        "defaultParams": true,
        "destructuring": true,
        "forOf": true,
        "generators": true,
        "modules": true,
        "newTarget": true,
        "objectLiteralComputedProperties": true,
        "objectLiteralDuplicateProperties": true,
        "objectLiteralShorthandMethods": true,
        "objectLiteralShorthandProperties": true,
        "octalLiterals": true,
        "regexUFlag": true,
        "regexYFlag": true,
        "restParams": true,
        "spread": true,
        "templateStrings": true,
        "unicodeCodePointEscapes": true
        "modules": true,
        "jsx": true
    }
}
.eslintrc(新)
{
    "parserOptions": {
        "ecmaVersion": 6,       // ES2015(ES6) の構文はここに集約
        "sourceType": "module", // Modules の指定だけは分離
        "ecmaFeatures": {       // ECMAScript に含まれない仕様はここ
            "jsx": true
        }
    }
}

JSX は残ってますね!

parserOptionsの中は、ESLint の設定ではなく espree (ESLint が使っている構文解析器) の設定です。そのため、parserオプションを指定して別の構文解析器 (babel-eslintとか) を使っている場合は、記述内容がまったく異なる可能性があります。具体的には各々の構文解析器プラグインの発表を参照してください。

ecmaVersion: 6を記載しても、ES2015(ES6) の新しいグローバル変数は定義されません (構文解析器のオプションなので)。他方でenv: {es6: true}を記載すると、構文解析器は ES2015(ES6) の構文を解析するようになり、かつES2015(ES6) の新しいグローバル変数が定義されます。envは複合的な設定セットなのです。
そのため、できる限りparserOptionsよりもenvを使うようにしましょう。

.eslintrc(ES6)
{
    "env": {"es6": true} // <-- ES6 機能を有効にして ES6 の新しい変数を定義する
}
.eslintrc(ES6+Modules)
{
    "env": {"es6": true},                     // <-- ES6 機能を有効にして ES6 の新しい変数を定義する
    "parserOptions": {"sourceType": "module"} // <-- コードをモジュールとして扱う
}

また、特定の構文だけ無効化したい場合は、no-restricted-syntax ルールを利用することになります。

Node.js 向けの場合は、eslint-plugin-node プラグインの node/no-unsupported-features ルールを利用することができます。このルールは、Node.js のバージョンを指定すると、そのバージョンでサポートされていない ES6 機能を警告します。

.eslintrc
{
    "plugins": ["eslint-plugin-node"],
    "env": {"es6": true, "node": true},
    "rules": {
        "node/no-unsupported-features": [2, {"version": 4}] // <-- Node.js v4.x (Argon) でサポートされない ES6 機能を警告する
    }
}

"eslint:recommended"がルール本来の振る舞いを変更しないようになった (#4809)

func-style ルールのデフォルトの振る舞いは"expression"ですが、"eslint:recommended""declaration"で上書きしてしまっていました。
そのため、"eslint:recommended"を指定している場合と、いない場合とで"func-style"のデフォルトの振る舞いが変化していました。

.eslintrc
{
    "rules": {
        "func-style": 2 // `expression` by default.
    }
}
.eslintrc
{
    "extends": "eslint:recommended",
    "rules": {
        "func-style": 2 // `declaration` by default.
    }
}

これは非常に混乱する動作なので、v2.0.0 では上書きしないようになりました。
あなたが"eslint:recommended"を利用していて、以前の振る舞いに戻したい場合は、次のようにfunc-styleの設定を追加してください。

.eslintrc
{
    "extends": "eslint:recommended",
    "rules": {
        "func-style": [2, "declaration"]
    }
}

--config CLI オプションを利用する場合、~/.eslintrcが読み込まれなくなった (#4881)

もともと、プロジェクトに設定ファイルがある場合は ~/.eslintrc は読み込まれないことになっていました。この修正は、チェック漏れしていたバグの修正です。

~/.eslintrc を利用するとチームと守るべきルールを合わせることが困難になります。
OSS の場合も重要で、予期せず~/.eslintrcが使われると PR を送った後で CI に怒られるかもしれません。

"eslint:recommended"で有効になるルールが追加された (#4953)

これまで、"eslint:recommended"ではここに挙げる32個のルールを有効にしていました。ESLint v2.0.0 では、加えて以下の11個のルールも有効になります。

  • constructor-super - 基底クラスがあるクラス定義のコンストラクタでsuper()を呼び出していない場合に警告します。JavaScript では、基底クラスがあるクラス定義でsuper()を省略できない (実行時エラーになる) ため、重要です。
  • no-case-declarations - switch文のブロックで Block-Scoped の変数宣言を禁止します。これは、case句がスコープを作らないために、意図しない TDZ エラーの原因となるためです。
  • no-class-assign - クラス宣言文によって作られた変数への再代入を禁止します。
  • no-const-assign - const宣言によって作られた変数への再代入を禁止します。常に実行時エラーになるためです。
  • no-dupe-class-members - クラス定義の中に名前が重複するメソッドがあると警告します。
  • no-empty-pattern - Destructuring Assignments にて、空の分解パターンを禁止します。それは構文上許されていますが、何もしません (このルールができたことをきっかけに、仕様から削除するか議論されました)。
  • no-new-symbol - new Symbol()を警告します。常に実行時エラーになるためです。
  • no-self-assign - 自己代入を警告します。foo = foo;[a, b] = [a, x];のようなコードが警告されます。
  • no-this-before-super - 基底クラスがあるクラス定義において、super()の前にthis.でプロパティ アクセスをしていたら警告します。それらは常に実行時エラーになるためです。
  • no-unexpected-multiline - セミコロンを省略するスタイルにおいて、適切に ASI が行われない場所を警告します。
  • no-unused-labels - 未使用のラベルを警告します。no-unused-vars のラベル版です。

追加されたルールの多くは、ES2015 (ES6) 関連ルールですね。
"eslint:recommended"には、「好みが分かれるスタイル・ルールは含めず、エラーの原因になるルールだけを厳選して有効にする」というポリシーがあります。ぜひとも利用しましょう。

.eslintrc
{
    "extends": ["eslint:recommended"],
    "rules": {
    }
}

extends/parserの名前解決が.eslintrcから相対的に行われるようになった (#4985, #5023, #5164)

  • ローカル・インストールされた ESLint では、.eslintrcがあるディレクトリからextends/parserの検索を開始します。これにより、共有設定が、依存する共有設定やパーサーをモジュール内に持てるようになります。
  • グローバル・インストールされた ESLint では、これまで通り単にrequire()します。

プラグイン製作者向け

新機能 - New Features

• 実行パス解析 (#3530)

コードがどのような分岐を持っているかを静的解析し、分岐ごとの情報をストアしたり、分岐が合流するときに reduce したりできます。
この機能により、no-unreachable, no-fallthrough等の一部のルールがより正確に誤りを検出するようになりました。

もちろん、プラグインからもこの機能を利用できます。
マニュアルはこちら

使い方がわからん! という方は私に質問ください。私が書いた機能なので。

• プラグインが独自のextends設定を提供できるようになった (#3659)

かねてより「プラグイン(eslint-plugin-foo)と共有設定(eslint-config-foo)の両方を作るのは面倒なので、プラグインの中で共有設定を書けるようにしてくれ (あるいは逆に共有設定がプラグインルールを直接持てるようにしてくれ)」という要望がありました。

今回、プラグインが共有設定を提供できるようになります。

eslint-plugin-myplugin/index.js
module.exports = {
    rules: {},
    configs: {
        recommended: {
            env: {es6: true},
            rules: {
                "myplugin/awesome-rule": 2
            }
        }
    }
};

などと記述すると、プラグイン利用者はmyplugin/recommendedという名前のextendsを利用できるようになります。

.eslintrc
{
    "plugins": ["myplugin"],
    "extends": ["eslint:recommended", "plugin:myplugin/recommended"]
}

ただし、共有設定と区別するためにplugin:接頭辞が必要になります。

• 現在利用されている構文解析器へのパスを取得できるようになった (#3670)

context.parserPathプロパティを参照することで、現在利用されている構文解析器へのパスを取得できるようになりました。プラグイン・ルールが、他ファイルの解析結果を使って検証をしたい場合に便利です。

CLIEngine API にcwdオプションが追加された (#4472)

Atom 等のエディタ プラグインでこれがあると便利なようです。

• プラグインが独自のenv設定を提供できるようになった (#4782)

ESLint の設定にはenvという項目があります。これはグローバル変数と構文解析オプションを組み合わせて提供するものです。組込み値としてnode, browser, es6などが提供されています。
ここに、プラグイン固有のenvを追加できるようになりました。

eslint-plugin-myplugin/index.js
module.exports = {
    rules: {},
    environments: {
        custom: {
            globals: { "$": true }
            parserOptions: { ecmaVersion: 6 }
        }
    }
};

などと記述すると、プラグイン利用者はcustomという名前のenvを利用できるようになります。

.eslintrc
{
    "plugins": ["myplugin"],
    "env": {
        "myplugin/custom": true
    }
}

仕様変更 - Breaking Changes

• オプション スキーマ定義が改善された (#3625)

オブジェクト形式のスキーマ定義を利用している場合、従来はオプションとは無関係の警告レベルについても記述する必要がありました。

従来
module.exports.schema = {
    "type": "array",
    "items": [
        {"enum": [0, 1, 2]},          // 警告レベル設定。オプションじゃなくね?
        {"enum": ["always", "never"]} // オプション。
    ],
    "minItems": 1,
    "maxItems": 2
};

これが不要になります。

2.0.0
module.exports.schema = {
    "type": "array",
    "items": [
        {"enum": ["always", "never"]}
    ],
    "minItems": 0,
    "maxItems": 1
};

RuleContextオブジェクトがfreezeされるようになった (#4495)

プラグインや独自ルールがRuleContextオブジェクトにプロパティを追加している場合、修正が必要になります。

module.exports = function(context) {
    context.myUtil = {}; // Ouch!

    return {};
};

• スコープ解析結果が改善された (#4615)

スコープ解析において、VariableオブジェクトとReferenceオブジェクトの間の関連が正しく作られるようになりました。
従来は多くのグローバル変数について関連が作成できず、多くのReferenceオブジェクトが「変数が未定義」な状態になっていました。そのため、グローバル変数を扱うルールはそれぞれワークアラウンドを書く必要がありました。
2.0.0からは、これらのワークアラウンドが不要になります (例えばこんなワークアラウンドがありました)。

これに伴い、(Global の) Scopeオブジェクトのthroughプロパティ (変数が見つからなかったReferenceオブジェクトの配列)が、"存在するグローバル変数のReferenceオブジェクト" を含まなくなりました。あなたのプラグインや独自ルールが "存在するグローバル変数のReferenceオブジェクト" を探すためにScope#throughを利用している場合、修正が必要になります。

従来
var globalScope = context.getScope();
globalScope.through.forEach(function(reference) {
    if (reference.identifier.name === "window") {
        checkForWindow(reference);
    }
});
v2.0.0
var globalScope = context.getScope();
var variable = globalScope.set.get("window");
if (variable) {
    variable.references.forEach(checkForWindow);
}

ecmaFeatures設定項目が廃止された (#4641)

詳しくは利用者向けの解説を参照ください。
プラグインや独自ルールの中でこの設定を参照している場合、修正が必要になります。

• Unicode Byte Order Mark が予め除去されるようになった (#4878)

構文解析の前に BOM が除去されるようになりました。
プラグイン・ルールの中からファイルに BOM があるかを調べるにはcontext.getSourceCode().hasBOMを参照します。

• プラグインの各ルールのデフォルト設定が廃止された (#4952)

ESLint は v1.0.0 からデフォルトではすべてのルールが OFF になっています。プラグインの各ルールの ON/OFF のデフォルト値を提供するruleConfig設定は、互換性のために残されましたが非推奨となっていました。
今回、このruleConfig設定が正式に削除されました。

eslint-plugin-myplugin/index.js
module.exports = {
    rules: {
        "foo-rule": require("lib/rules/foo-rule")
    },
    // `ruleConfig`設定によって、プラグインのルールをデフォルトで ON にできていた (非推奨だった)。
    ruleConfig: {
        "foo-rule": 2
    }
};

できなくなります。
代替手段としてeslint:recommendedのような独自の"extends"設定を提供できるようになります。