Skip to content

Commit 1930e40

Browse files
authored
fix(eslint): ESLintのautofixに対応 (#132)
* fix(eslint): ESLintのautofixに対応 * chore: mocha@8 * fix(eslint): update code example * refactor: use const instead of let * fix * fix * fix * fix * fix * fix
1 parent b383d90 commit 1930e40

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+3864
-2390
lines changed

.eslintrc

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"always"
1818
],
1919
"no-console": 0,
20-
"no-var": 2
20+
"no-var": 2,
21+
"prefer-const": "error"
2122
},
2223
"env": {
2324
"es6": true,
@@ -30,4 +31,4 @@
3031
"sourceType": "module"
3132
},
3233
"extends": "eslint:recommended"
33-
}
34+
}

.mocharc.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"timeout": "100000",
3+
"recursive": true,
4+
"require": [
5+
"@babel/register"
6+
]
7+
}

ja/ESLint/README.md

+29-25
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
# ESLint
22

3-
> この文章は[ESLint](http://eslint.org/ "ESLint") 1.3.0を元に書かれています
3+
> この文章は[ESLint](http://eslint.org/ "ESLint") v7.8.1を元に書かれています
44
55
[ESLint](http://eslint.org/ "ESLint")はJavaScriptのコードをJavaScriptで書かれたルールによって検証するLintツールです。
66

77
大まかな動作としては、検証したいJavaScriptのコードをパースしてできたAST(抽象構文木)をルールで検証し、エラーや警告を出力します。
88

99
このルールがプラグインとして書くことができ、ESLintのすべてのルールはプラグインとして実装されています。
1010

11-
> The pluggable linting utility for JavaScript and JSX
11+
> Find and fix problems in your JavaScript code
1212
1313
ESLintサイト上には、上記のように書かれていることからもわかりますが、プラグインに重きを置いた設計となっています。
1414

1515
今回はESLintのプラグインアーキテクチャがどうなっているかを見て行きましょう。
1616

1717
## どう書ける?
1818

19-
ESLintでは`.eslintrc`という設定ファイルに利用するルールの設定をして使うため、
20-
実行方法についてはドキュメントを参照してください。
19+
ESLintでは`.eslintrc`という設定ファイルに利用するルールを設定して利用します。
20+
そのため、実行方法についてはドキュメントを参照してください。
2121

2222
- [Documentation - ESLint - Pluggable JavaScript linter](http://eslint.org/docs/user-guide/configuring "Documentation - ESLint - Pluggable JavaScript linter")
2323

24-
ESLintにおけるルールとは、次のような関数をexportしたモジュールです
25-
関数には`context`オブジェクトが渡されるので、それに対して1つのオブジェクトを返すようにします。
24+
ESLintにおけるルールとは、次のような`create`メソッドをもつオブジェクトをexportしたモジュールです
25+
`create`メソッドには`context`オブジェクトが渡されるので、それに対して1つのオブジェクトを返すようにします。
2626

2727
[import, no-console.js](../../src/ESLint/no-console.js)
2828

@@ -75,8 +75,8 @@ console.log("Hello!");
7575

7676
ESLintではこのASTを使って、[no-console.js](#no-console.js)のように`console.log`などがコードに残ってないかなどをルールを元にチェックできます。
7777

78-
ルールをどう書けるかという話に戻すと、`context`というオブジェクトはただのユーティリティ関数と考えて問題ありません
79-
ルールの本体は関数が`return`してるメソッドをもったオブジェクトです。
78+
ルールをどう書けるかという話に戻すと、`context`というオブジェクトはただのユーティリティ関数の集合と考えて問題ありません
79+
ルールの本体は`create`メソッドが`return`してるメソッドをもったオブジェクトです。
8080

8181
このオブジェクトはNodeのtypeをキーとしたメソッドを持っています。
8282
そして、ASTを探索しながら「`"MemberExpression"` typeのNodeに到達した」と登録したルールに対して通知(メソッド呼び出し)を繰り返しています。
@@ -101,7 +101,7 @@ ESLintではこのASTを使って、[no-console.js](#no-console.js)のように`
101101
[no-console.js](#no-console.js)のルールを見ると`MemberExpression` typeのNodeが `node.object.name === "console"` となった場合に、
102102
`console`が残ってると判断してエラーレポートすると読めてくると思います。
103103

104-
ASTの探索がイメージしにくい場合は次のルールで探索の動作を見てみると分かりやすいかもしれません
104+
ASTの探索がイメージしにくい場合は、次のルールで探索の動作を見てみると分かりやすいかもしれません
105105

106106
- [azu.github.io/visualize_estraverse/](http://azu.github.io/visualize_estraverse/ "visualize estraverse step")
107107

@@ -120,7 +120,7 @@ debug("Hello");
120120

121121
その他、ESLintのルールの書き方についてはドキュメントや次の記事を見てみるといいでしょう。
122122

123-
- [Documentation - ESLint - Pluggable JavaScript linter](http://eslint.org/docs/developer-guide/working-with-rules "Documentation - ESLint - Pluggable JavaScript linter")
123+
- [Working with Rules - ESLint - Pluggable JavaScript linter](https://eslint.org/docs/developer-guide/working-with-rules)
124124
- [コードのバグはコードで見つけよう!|サイバーエージェント 公式エンジニアブログ](http://ameblo.jp/principia-ca/entry-11837554210.html "コードのバグはコードで見つけよう!|サイバーエージェント 公式エンジニアブログ")
125125

126126
## どのような仕組み?
@@ -148,22 +148,22 @@ import {EventEmitter} from "events";
148148

149149
function lint(code){
150150
// コードをパースしてASTにする
151-
let ast = parse(code);
151+
const ast = parse(code);
152152
// イベントの登録場所
153-
let emitter = new EventEmitter();
154-
let results = [];
153+
const emitter = new EventEmitter();
154+
const results = [];
155155
emitter.on("report", message => {
156156
// 3. のためのreportされた内容を集める
157157
results.push(message);
158158
});
159159
// 利用するルール一覧
160-
let ruleList = getAllRules();
160+
const ruleList = getAllRules();
161161
// 1. ルール毎に使っている`Node.type`をイベント登録する
162162
ruleList.forEach(rule => {
163163
// それぞれのルールに定義されているメソッド一覧を取得
164164
// e.g) MemberExpression(node){}
165165
// => {"MemberExpression" : function(node){}, ... } というオブジェクト
166-
let methodObject = getDefinedMethod(rule);
166+
const methodObject = getDefinedMethod(rule);
167167
Object.keys(methodObject).forEach(nodeType => {
168168
emitter.on(nodeType, methodList[nodeType]);
169169
});
@@ -245,27 +245,31 @@ add(1, 3);
245245
このプラグインアーキテクチャはPub/Subパターンを上手く使い、
246246
ESLintのように与えられたコードを読み取ってチェックするような使い方に向いています。
247247

248-
つまり、read-onlyなプラグインアーキテクチャとしてはパフォーマンスも期待できると思います。
248+
つまり、複数のルールで同時にLintをするというread-onlyなプラグインアーキテクチャとしてはパフォーマンスも期待できると思います。
249249

250-
また、ルールは `context` という与えられたものだけを使うようになっているため、ルールと本体が密結合にはなりにくいです。
251-
そのため`context`に何を与えるかを決めることで、ルールが行える範囲を制御しやすいといえます
250+
また、ルールは `context` オブジェクトという与えられたものだけを使うようになっているため、ルールと本体が密結合にはなりにくいです。
251+
そのため`context`に何を与えるかを決めることで、ルールができる範囲を制御しやすいといえます
252252

253253
## どのような用途に向いていない?
254254

255255
逆に与えられたコード(AST)を書き換える場合には、
256-
ルールを同時に処理を行うためルール間で競合するような変更がある場合に破綻してしまいます
256+
ルールを同時に処理を行うためルール間で競合するような変更がある場合に上手く整合性を保つ必要があります
257257

258-
そのため、この仕組みに加えてもう1つ抽象レイヤーを設けないと対応は難しいです。
258+
たとえば、あるルールが書き換えるとコードの位置に更新がかかるため、その後のルールはコードの位置更新の影響を受けます。
259+
そのため、コードの書き換えをするにはこの仕組みに加えて、もう1つ抽象レイヤーを設けないと対応は難しいです。
259260

260-
つまり、read-writeなプラグインアーキテクチャとしては単純にこのパターンだけでは難しい部分が出てくると思います
261+
つまり、read-writeなプラグインアーキテクチャとしては、このパターンだけでは難しい部分が出てくると思います
261262

262-
> **NOTE** ESLint 2.0でautofixing、つまり書き換えの機能の導入が予定されています。
263-
> これはルールからの書き換えのコマンドを`SourceCode`というオブジェクトに集約して、最後に実際の書き換えを行うという抽象レイヤーを設けています。
263+
> **NOTE** ESLint 2.0からautofix、つまり書き換えの機能の導入が導入されています
264+
> ESLintでは、各ルールが書き換える位置や文字列を`fixer`オブジェクトという形で報告し、ESLint本体がルールの順番を考慮して最後に実際の書き換えを行うという抽象レイヤーを設けています。
265+
> これは[Command パターン](https://ja.wikipedia.org/wiki/Command_%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)を利用してトランザクション的なふるまいを実現しています。
264266
> - [Implement autofixing · Issue #3134 · eslint/eslint](https://github.com/eslint/eslint/issues/3134 "Implement autofixing · Issue #3134 · eslint/eslint")
265267
266268
## この仕組みを使っているもの
267269

268-
- [azu/textlint](https://github.com/azu/textlint "azu/textlint")
270+
- [stylelint](https://github.com/stylelint/stylelint)
271+
- CSSのLintするツール
272+
- [textlint](https://github.com/textlint/textlint)
269273
- テキストやMarkdownをパースしてASTにしてLintするツール
270274

271275
## エコシステム
@@ -293,7 +297,7 @@ ESLint公式の設定として`eslint:recommended`が用意されています。
293297
設定なしで使えると一番楽ですが、設定なしだと誰でも使えるツールにするのは難しいです。
294298
それを解消するために柔軟な設定のしくみと設定を共有しやすくしています。
295299

296-
これは_The pluggable linting utility_を表現している仕組みといえるかもしれません
300+
これは_Pluggable JavaScript linter_を表現している仕組みといえるかもしれません
297301

298302
## まとめ
299303

ja/connect/README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ Connectは登録された _middleware_ を、サーバがリクエストを受
9191
Connectの行っている処理を抽象的なコードで書くと次のような形になっています。
9292

9393
```js
94-
let req = "...",
94+
const req = "...",
9595
res = "...";
9696
function next(){
97-
let middleware = app.stack.shift();
97+
const middleware = app.stack.shift();
9898
// nextが呼ばれれば次のmiddleware
9999
middleware(req, res, next);
100100
}

ja/gulp/README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ gulp.task("sass", function() {
8080
[gulp-prefixer.js](#gulp-prefixer.js)を見てみると、`gulpPrefixer`という[Transform Stream](https://nodejs.org/api/stream.html#stream_class_stream_transform "stream.Transform")のインスタンスを返していることが分かります。
8181

8282
```js
83-
let gulpPrefixer = function (prefix) {
83+
const gulpPrefixer = function (prefix) {
8484
// enable `objectMode` of the stream for vinyl File objects.
8585
return new Transform({
8686
// Takes in vinyl File objects
@@ -185,8 +185,8 @@ gulp.src("./*.*")
185185

186186
```js
187187
gulp.src("./*.*", { buffer: false })
188-
.pipe(gulpPrefixer("prefix text"))
189-
.pipe(gulp.dest("build"));
188+
.pipe(gulpPrefixer("prefix text"))
189+
.pipe(gulp.dest("build"));
190190
```
191191

192192
### 変換処理
@@ -203,7 +203,7 @@ export function prefixStream(prefix) {
203203
transform: function (chunk, encoding, next) {
204204
// ObjectMode:falseのTransform Stream
205205
// StreamのchunkにはBufferが流れてくる
206-
let buffer = prefixBuffer(chunk, prefix);
206+
const buffer = prefixBuffer(chunk, prefix);
207207
this.push(buffer);
208208
next();
209209
}

0 commit comments

Comments
 (0)