久方ぶりの jshint jslint eslint

これは 2015年10月、ということは 2年と4ヶ月ぶり、てことか。

mocha よりも先にやれや、つー話ではあって、雑にやってたんでこういう順序になっちゃった。

して、2年と4ヶ月ぶりに npm -g install jshint jslint eslint したら、+ jslint@0.12.0、+ eslint@4.17.0、+ jshint@2.9.5 になった。

前回やったときは「;チェックしてくれたりせんかねぇ」しか興味がなかったんで、も少し良さを探ってみましょうかね、てことである。もうこんなん TDD サイクルの中に突っ込んでしまいたいわけだわよ。


まず「生まれたて」のままで「剥き身で」使ってみる。つまり、「ただチェック対象 js ファイルを渡すだけ」。理想的には mocha テストしてるテスト js 内でダイレクトに呼び出したいが、ひとまずは。

まず jslint:

1 [me@host: ~]$ jslint page_parse.js
2 
3 page_parse.js
4  #1 Unexpected 'const'.
5     const util = require('util'); // Line 6, Pos 1
6  #2 Stopping. (0% scanned).
7      // Line 6, Pos 7

うん、もうダメだね、これは。最近の ecmascript 標準の書き方、だと思ってるんだけど、多分それに追従出来てないんだろうなぁ。

と最初思ったんだけど、ドキュメント

Added latest jslint, 2016-07-13.
Version 0.10.3 contains the latest jslint-es6

なんて書いてあるんだわ。なんぢゃこりゃ、と少々迷走し、やっと理解:

 1 [me@host: ~]$ jslint --edition=2016-07-13 _page_parsers_code.js
 2 
 3 _page_parsers_code.js
 4  #1 Expected an identifier and instead saw '}'.
 5     }[m[1]]; // Line 33, Pos 4
 6  #2 Unexpected TODO comment.
 7     // TODO: "&", "#", ";" // Line 58, Pos 12
 8  #3 Unexpected TODO comment.
 9     // todo?: for example, type=1 means "type=TV", etc. // Line 121, Pos 4
10  #4 Expected '"' and instead saw '''.
11     '(?:<div[^<>]*>)? *<a href="[^"]*/([0-9]+)/([^/"<>]+)(?:/.*)?" *(?:id="[^"]+")?> *<img [a-z-]*src="([^"]*)"[^<>]*> *</a> *(?:</div>)?'); // Line 131, Pos 9
12           ...

なんちゃぁわかりにくい。ただチェックは結構面白いことやってるね。TODO コメントの書き方のスタイルまであるわけか。なんかの IDE が前提にするんだろうなぁ。


次、eslint

 1 [me@host: ~]$ eslint page_parse.js
 2 
 3 Oops! Something went wrong! <img src="http://hhsprings.pinoko.jp/site-hhs/wp-includes/images/smilies/icon_sad.gif" alt=":(" class="wp-smiley" />
 4 
 5 ESLint: 4.17.0.
 6 ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:
 7 
 8     eslint --init
 9 
10 ESLint looked for configuration files in c:\Users\hhsprings\__ttmp2\myanimelist_stats\scripts\client_side_only_approach and its ancestors. If it found none, it then looked in your home directory.
11 
12 If you think you already have a configuration file or if you need more help, please stop by the ESLint chat room: https://gitter.im/eslint/eslint

なんですと? いやぁ、前試したヤツはこんなじゃなかったぞ。

1 [me@host: ~]$ eslint --init
2    ... (メニュー形式で質問されるので、それに答えていくことで configuration が作られる)...

注意しなければならないのは、コンソールに色を付けて質問してくるのだが、「文字色として白を使っている」ので、設定を変えて白背景にしてると読めないこと。なんだかなぁ。もう一つが、「予め npm init して package.json を作っとくべし」なんだとさ。うーん、前に mocha でこれ言われてサボるんじゃなかった。

ともあれ「こういうチェックにしたいんじゃぁ」が、全然柔軟だね。「セミコロンを必要とする?」とか色々質問された。(plugin が必要になるので、yes 選びすぎないこと。)

てわけで改めて:

 1 [me@host: ~]$ eslint page_parse.js
 2 
 3 c:\...\page_parse.js
 4      1:4    error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
 5      2:33   error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
 6      3:12   error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
 7      4:28   error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
 8      5:4    error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
 9      6:7    error  'util' is assigned a value but never used                                no-unused-vars
10      6:22   error  Strings must use doublequote                                             quotes
11      6:29   error  Extra semicolon                                                          semi
12 ...
13   1418:7    error  Extra semicolon                                                          semi
14   1418:8    error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
15   1419:3    error  Extra semicolon                                                          semi
16   1419:4    error  Expected linebreaks to be 'LF' but found 'CRLF'                          linebreak-style
17 
18 笨・2284 problems (2284 errors, 0 warnings)
19   2203 errors, 0 warnings potentially fixable with the `--fix` option.

改行コードはワタシとしては Unix スタイルとしてチェックしたいが、今暫定で「python で javascript を生成」してるために DOS スタイルになっちゃってて検出されちゃってる。ただ、「チェックして欲しいなぁ」をかなりチェックしてくれてる。いいね、まずはいい感じ。

そもそも例えば「引用符は二重引用符に統一したいなぁ」なんて思ってたので、これをチェック出来るってだけでもすんげー嬉しい、と初見では思った。ただ、実際のとこは「文字列内に二重引用符を含んでるなら単一引用符で」という当たり前の小技まで拒絶しちゃうので…、なんか逆に「チェックしないでくれ」コンフィグはないのかしら、と思う。ドキュメントであっさり解決。eslint --init で作られた .eslintrc.js で「off」にすればいいだけだね。

なんにしても、前に使ったときとは全然違ってないすかね、この子。


最後、jshint

 1 [me@host: ~]$ jshint page_parse.js
 2 page_parse.js: line 6, col 1, 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
 3 page_parse.js: line 8, col 1, 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
 4 page_parse.js: line 9, col 1, 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
 5 page_parse.js: line 10, col 1, 'const' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
 6 page_parse.js: line 27, col 13, Misleading line break before '+'; readers may interpret this as an expression boundary.
 7 page_parse.js: line 28, col 13, Misleading line break before '+'; readers may interpret this as an expression boundary.
 8 page_parse.js: line 29, col 13, Misleading line break before '+'; readers may interpret this as an expression boundary.
 9 page_parse.js: line 56, col 2, Missing semicolon.
10 page_parse.js: line 59, col 2, Missing semicolon.
11 page_parse.js: line 88, col 2, Missing semicolon.
12 page_parse.js: line 97, col 2, Missing semicolon.
13 page_parse.js: line 105, col 2, Missing semicolon.
14 page_parse.js: line 113, col 2, Missing semicolon.
15 page_parse.js: line 127, col 2, Missing semicolon.
16 page_parse.js: line 136, col 2, Missing semicolon.
17 page_parse.js: line 211, col 44, Functions declared within loops referencing an outer scoped variable may lead to confusing semantics.
18 page_parse.js: line 222, col 2, Missing semicolon.
19 page_parse.js: line 228, col 2, Missing semicolon.
20 page_parse.js: line 234, col 2, Missing semicolon.
21 page_parse.js: line 251, col 2, Missing semicolon.
22 page_parse.js: line 301, col 19, ['p'] is better written in dot notation.
23 page_parse.js: line 305, col 11, ['n'] is better written in dot notation.
24 page_parse.js: line 309, col 25, ['n'] is better written in dot notation.
25 page_parse.js: line 311, col 27, ['n'] is better written in dot notation.
26 page_parse.js: line 312, col 19, ['n'] is better written in dot notation.
27 page_parse.js: line 315, col 62, ['n'] is better written in dot notation.
28 page_parse.js: line 329, col 24, ['defail_fields'] is better written in dot notation.
29 page_parse.js: line 330, col 23, ['defail_fields'] is better written in dot notation.
30 page_parse.js: line 338, col 51, Missing semicolon.
31 page_parse.js: line 350, col 11, ['dtl'] is better written in dot notation.
32 page_parse.js: line 361, col 27, ['dtl'] is better written in dot notation.
33 page_parse.js: line 369, col 31, ['dtl'] is better written in dot notation.
34 page_parse.js: line 372, col 31, ['dtl'] is better written in dot notation.
35 page_parse.js: line 374, col 31, ['dtl'] is better written in dot notation.
36 page_parse.js: line 377, col 27, ['dtl'] is better written in dot notation.
37 page_parse.js: line 379, col 27, ['dtl'] is better written in dot notation.
38 page_parse.js: line 384, col 15, ['dtl'] is better written in dot notation.
39 page_parse.js: line 384, col 22, ['family_name'] is better written in dot notation.
40 page_parse.js: line 384, col 47, ['dtl'] is better written in dot notation.
41 page_parse.js: line 384, col 54, ['given_name'] is better written in dot notation.
42 page_parse.js: line 385, col 19, Missing semicolon.
43 page_parse.js: line 386, col 19, ['dtl'] is better written in dot notation.
44 page_parse.js: line 386, col 26, ['family_name'] is better written in dot notation.
45 page_parse.js: line 387, col 26, ['dtl'] is better written in dot notation.
46 page_parse.js: line 387, col 33, ['family_name'] is better written in dot notation.
47 page_parse.js: line 389, col 19, ['dtl'] is better written in dot notation.
48 page_parse.js: line 389, col 26, ['given_name'] is better written in dot notation.
49 page_parse.js: line 390, col 26, ['dtl'] is better written in dot notation.
50 page_parse.js: line 390, col 33, ['given_name'] is better written in dot notation.
51 page_parse.js: line 392, col 15, ['j'] is better written in dot notation.
52 page_parse.js: line 392, col 15, Too many errors. (27% scanned).
53 
54 51 errors

dot notation の方がええぜ、ってそうなの? そうは書けないパターンがあるんで、統一的に square bracket notation にしてたんだけど。うーん、これに従いたいかどうかは微妙だなぁ。でもほかのチェックはいい感じだね。


それぞれ一長一短がある感じで、どれかだけがきゃーすてきぃ、て感じではないね。

あとは「mocha ってる中に入れてしまいたい」は、おいおいで、だな。今のところはコンソールで都度叩いてても大した手間ではない。でも jslint では少なくとも「出来る」ことは見えてる。いずれ遊んでみよう。


12:40追記:
JSLint の edition 指定出来るのはいいのだが、「何を使えるのか」がドキュメント上列挙されていないので困っていた。これ見ろってことかい?

てわけで、「本日」時点では 2018-01-26 が使えるってことかい? と思ったが、npm に登録されてるヤツだとまだこのマスターブランチの最新は取り込まれてない。ので、「本日時点で npm install で入手出来る JSLint」を使う場合の最新は 2017-07-01。

ただ、「特に設定せずに使う」場合、少なくともアタシのヤツ相手の場合はチェックしてくれる内容は変わってなさそうにみえる。ただし、「文言」は改善されてるみたい。ちゃんと「Use double quotes, not single quotes.」と言ってくれるようになった。「Expected ‘”‘ and instead saw ”’.」ではなく。


13:30追記:
JSLint の TODO に対する指摘、何を言いたいんだろうと思っていたのだが、なんか JSLint って、ぶっきらぼうなのがダメだわな。普通こういうのってさ、「どういう害悪が起こるから云々」な rationale がどっかに詳しく書かれてないと「従えない」んだよ。こっちだってバカじゃないんだから、「機械さまさまが正しいことを言ってるのでバカなので従いマッス」なんて出来るわけねーじゃん? そういう意味だけで言えば、JSLint はかなり零点だわ。

というのはあるけれど、無論「意味さえわかれば従うわいさ」と、「ソースを解読」するというハメに出た。

あ、単に「んなもん残しとくなや」てだけな。製品コードに TODO 残ってたらそりゃダメだわ。というわけで、多分だけど「--dev」オプションとか付けとけば文句言わなくなると思うし、ついでに「TODO なんか残しとくなや、全部潰すのが筋でしょーが」という小言は貴重、というか「便利」よね。(ただ、「言い回し」はなんとかならんのかいな、と思う。ほかと同じノリで「Unexpected」言われると「書き方が悪い」と思うじゃねーか。)


13:50追記:
JSLint が「ダメ」と言った同じ理由で ESLint は「大変良く出来ました」、になってて、いちいちわかりやすい

ただし、「従える」かどうかは別問題。これ:

1 q.replace(/\n$/, "")

みたいなのに対して ESLint は「Unexpected control character(s) in regular expression: \x0a」と不平を言うが、その根拠が「Control characters are special, invisible characters in the ASCII range 0-31. These characters are rarely used in JavaScript strings so a regular expression containing these characters is most likely a mistake.」。弱い。もう一声ないと共感出来ない。

今の例の場合、\s が使える場合はそうすればいいのだが、「改行コードだけ」を扱いたい場合は \s を使うわけにはいかない。つまり、\x20 は \x20 のままで、\x0a だけ取り除きたい、なんてのは滅茶苦茶普通にあるニーズ。としてみれば「rarely」でもなんでもないし、そもそも「rarely」だけじゃ根拠にならんじょ。

ただ、ワタシのケースに関して言えば「なんだ \s でもいいじゃん」というとこもあったので、「気付かせてくれてありがとう」ではあった。なのでチェックしていること自体が間違ってるとまでは言えない。のでやっぱ「根拠」をもちっと具体的に書いて欲しいね。(というか new RegExp スタイルで書く場合は「new RegExp(“\\s”, “g”)」という具合に \\s としなければならんことを今知った。)



Related Posts