Skip to content

Commit b001c43

Browse files
committed
feat(ESLint): 実装についてを追加
1 parent a178012 commit b001c43

File tree

5 files changed

+86
-8
lines changed

5 files changed

+86
-8
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
* [README](README.md)
44
* [Introduction](ja/introduction/README.md)
55
* [jQuery](ja/jQuery/README.md)
6+
* [ESLint](ja/ESLint/README.md)
67

ja/ESLint/README.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# ESLint
2+
3+
[ESLint](http://eslint.org/ "ESLint")はJavaScriptのコードをJavaScriptで書かれたルールによって検証するLintツールです。
4+
5+
大まかな動作としては、検証したいJavaScriptのコードをパースしてできたAST(抽象構文木)を、ルールで検証し、エラーや警告を出力します。
6+
7+
このルールがプラグインとして書けるようになっていて、ESLintの全てのルールがプラグインとして実装されています。
8+
9+
> The pluggable linting utility for JavaScript and JSX
10+
11+
ESLintサイト上には、上記のように書かれていることからもわかりますが、プラグインに重きを置いた設計となっているので、
12+
今回はESLintのプラグインアーキテクチャについてを見て行きましょう
13+
14+
## どう書ける?
15+
16+
[import, no-console.js](../../src/ESLint/no-console.js)
17+
18+
## どういう仕組み?
19+
## どういう用途に向いている?
20+
## どういう用途に向いていない?
21+
## この仕組みを使ってるもの
22+
## 実装してみよう
23+
24+
今回は、ESLintのルールを解釈できるシンプルなLintの処理を書いてみます。
25+
26+
利用するルールは先ほども出てきた[no-console.js](#no-console.js)をそのまま使い、
27+
このルールを使って同じようにJavaScriptのコードを検証できる`MyLinter`を書いてみます。
28+
29+
### MyLinter
30+
31+
MyLinterは単純で以下の2つのメソッドを持つクラスとして実装しました。
32+
33+
- `MyLinter#loadRule(rule): void`
34+
- 利用するルールを登録する処理
35+
- `rule`[no-console.js](#no-console.js)がexportしたもの
36+
- `MyLinter#lint(code): string[]`
37+
- `code`を受け取りルールによってLintした結果を返す
38+
- Lint結果はエラーメッセージの配列とする
39+
40+
実際に実装したものが以下のようになっています。
41+
42+
[import, src/ESLint/MyLinter.js](../../src/ESLint/MyLinter.js)
43+
44+
MyLinterで[no-console.js](#no-console.js)を読み込ませて、
45+
46+
```js
47+
function add(x, y){{
48+
console.log(x, y);
49+
return x + y;
50+
}
51+
add(1, 3);
52+
```
53+
54+
というコードをLintしてみます。
55+
56+
[import, src/ESLint/MyLinter-example.js](../../src/ESLint/MyLinter-example.js)
57+
58+
コードには`console`というオブジェクトが含まれているので_"Unexpected console statement."_というエラーメッセージが取得出来ました。
59+
60+
### RuleContext
61+
62+
もう一度、[MyLinter.js](#MyLinter.js)を見てみると、`RuleContext`というシンプルなクラスがあることに気づくと思います。
63+
64+
この`RuleContext`はいわゆるルールから使えるユーティリティメソッドをまとめたもので、
65+
今回は`RuleContext#report`というエラーメッセージをルールからMyLinterへ通知するものだけを実装しています。
66+
67+
ESLintのプラグインアーキテクチャの特徴でもありますが、プラグインが本体の実装がについては知らなくて、
68+
Contextという本体から与えられたものだけを使うので、ルールが行える事を制御しやすい作りといえます。
69+
70+
## エコシステム

src/ESLint/MyLinter-example.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,14 @@ import MyLinter from "./MyLinter";
44
import noConsole from "./no-console";
55

66
let linter = new MyLinter();
7-
linter.loadPlugin(noConsole);
8-
var results = linter.lint(`console.log("test")`);
7+
linter.loadRule(noConsole);
8+
var code = `
9+
function add(x, y){{
10+
console.log(x, y);
11+
return x + y;
12+
}
13+
add(1, 3);
14+
`;
15+
var results = linter.lint(code);
916
assert(results.length > 0);
1017
assert.equal(results[0], "Unexpected console statement.");

src/ESLint/MyLinter.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,17 @@ class RuleContext extends EventEmitter {
77
this.emit("report", message);
88
}
99
}
10-
export default class MyLint {
10+
export default class MyLinter {
1111
constructor() {
1212
this._emitter = new EventEmitter();
1313
this._ruleContext = new RuleContext();
1414
}
1515

16-
loadPlugin(plugin) {
17-
var rule = plugin(this._ruleContext);
16+
loadRule(rule) {
17+
var ruleExports = rule(this._ruleContext);
1818
// on(nodeType, nodeTypeCallback);
19-
Object.keys(rule).forEach(nodeType => {
20-
this._emitter.on(nodeType, rule[nodeType]);
19+
Object.keys(ruleExports).forEach(nodeType => {
20+
this._emitter.on(nodeType, ruleExports[nodeType]);
2121
});
2222
}
2323

test/ESLint/MyLinter-test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import noConsole from "../../src/ESLint/no-console";
66
describe("MyLint", function () {
77
it("should load and lint", function () {
88
let linter = new MyLinter();
9-
linter.loadPlugin(noConsole);
9+
linter.loadRule(noConsole);
1010
var results = linter.lint(`console.log("test")`);
1111
assert(results.length > 0);
1212
assert.equal(results[0], "Unexpected console statement.");

0 commit comments

Comments
 (0)