しおしお

IntelliJ IDEAのことなんかを書いてます

JSLintについて調べてみた

JavaScriptの静的検査をやってねってタスクがふってきたので、JSLint(http://www.jslint.com/)でどんな検査ができるか調べてみました。

CIで実行できることが前提なのでjslint4java(http://code.google.com/p/jslint4java/)ってライブラリを使用するので、jslint4javaで使えるオプションのみ調べています。(一部よくわからないのが残っていますが)

ちなみに検査の根拠などは、以下の本に一部書かれています。

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

Tolerate bitwise operators

ビット演算子の使用をチェックします。
ビット演算子を許容する場合には、オプション「bitwise」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var num = 0;

  num &= 0;
  num ^= 0;
  num <<= 2;
}
検査結果
jslint:test.js:5:7:Unexpected '&='.
jslint:test.js:6:7:Unexpected '^='.
jslint:test.js:7:7:Unexpected '<<='.

Assume a browser

一般的なブラウザのグローバル変数の使用をチェックします。
宣言済みとみなす場合には、オプション「browser」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var XMLHttpRequest2 = new XMLHttpRequest();
  clearInterval(0);
}
検査結果
jslint:test.js:3:29:'XMLHttpRequest' was used before it was defined.
jslint:test.js:4:3:'clearInterval' was used before it was defined.

Tolerate HTML case

htmlタグが全て小文字であることをチェックします。
大文字を許容する場合は、オプション「cap」を指定します。

悪い例と検査結果

検査対象コード
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<Head>
    <Title></title>
</head>
<body>
</body>
</html>
検査結果

1つでもエラーがあったら検査終わり?

jslint:test.html:3:2:Expected 'html' and instead saw 'HTML'.
jslint:test.html:3:2:Stopping.  (33% scanned).

Tolerate continue

continue文の使用をチェックします。
continue文を許容する場合には、オプション「continue」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var n = 0;
  while (n < 100) {
    if (n % 2 === 0) {
      continue;
    }
  }
}
検査結果
jslint:test.js:6:7:Unexpected 'continue'.

Tolerate CSS workarounds

CSSの先頭行に「@charset」があるかをチェックします。
チェックを行わない場合には、オプション「css」を指定します。

悪い例と検査結果

検査対象コード
body {
    background-color: #f0ffff;
}
検査結果

メッセージから原因を特定するのは難しい気が・・・

jslint:test.css:1:1:'body' was used before it was defined.
jslint:test.css:1:6:Expected an operator and instead saw '{'.
jslint:test.css:1:6:Stopping.  (33% scanned).

Tolerate debugger statements

debugger文の使用をチェックします。
debugger文の使用を許容する場合には、オプション「debug」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  debugger;
}
検査結果
jslint:test.js:3:3:Unexpected 'debugger'.

Assume console, alert, ...

consoleやalertの使用をチェックします。
これらの機能の使用を許容する場合には、オプション「devel」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  console.log('log');
  alert('huga');
}
検査結果
jslint:test.js:3:3:'console' was used before it was defined.
jslint:test.js:4:3:'alert' was used before it was defined.

Tolerate == and !=

「==」や「!=」演算子の使用をチェックします。
「==」や「!=」を許容する場合には、オプション「eqeq」を指定します。

悪い例と検査結果

検査対象コード
var str = '';
if (str == '') {    // 許可されない「==」で比較している。
  str = 'hoge';
}
検査結果
jslint:test.js:2:9:Expected '===' and instead saw '=='.

Tolerate eval

eval関数の呼出をチェックします。
eval関数の呼出を許容する場合には、オプション「evil」を指定します。

eval関数の他にも、Function関数やsetTimeout等の呼出も制限できます。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var str = '',
    f;
  eval(str);
  f = new Function(0, 0, 0);
}
検査結果
jslint:test.js:6:3:eval is evil.
jslint:test.js:7:19:The Function constructor is eval.

Tolerate unfiltered for in

for-inループ内でオブジェクトのプロパティを参照する際には、自身のプロパティかのフィルタがかけられているかチェックします。
許容する場合には、オプション「forin」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var obj = new Array(10),
    key,
    arr = new Array(0);

  for (key in obj) {
    arr.push(obj[key]);     // hasOwnPropertyで自身のプロパティかのチェックをおこなっていない
  }
}
検査結果
jslint:test.js:7:3:The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.

Strict white space indentation

インデントのチェック。
デフォルトのチェックは「4」なので、変更する場合には「indent」オプションで指定する。

悪い例と検査結果

indentオプションに「2」を指定した場合(インデントは、2スペースが私の好み)

検査対象コード
function hoge() {
 "use strict";      // 1スペースしかない
  var fuga,
     i;             // 折り返し後が3スペースになっている
}
検査結果
jslint:test.js:2:2:Expected 'use strict' at column 3, not column 2.
jslint:test.js:4:6:Expected 'i' at column 5, not column 6.

Maximum number of errors

エラーとしてレポートする最大数を指定します。
デフォルトは「50」なので、変更する場合は「maxerr」オプションで指定してます。

指定数を超えると、以下の様なメッセージが出力されます。

jslint:test.js:2:2:Too many errors. (40% scanned).

Maximum line length

1行の共用する長さを指定します。デフォルトは無制限(何文字でもOK)?
値の指定は「maxlen」オプションに指定してます。

例えば、120文字を指定した場合で、120文字を超える行があった場合には、以下の様なメッセージが出力されます。

jslint:test.js:3:135:Line too long.

Tolerate uncapitalized constructors

String等のコンストラクタ呼出や、小文字から始まるコンストラクタをチェックします。(多分)
動作確認できず。

検査結果
jslint:test.js:8:15:A constructor name 'fuga' should start with an uppercase letter.
jslint:test.js:9:15:Do not use String as a constructor.

Tolerate dangling _ in identifiers

アンダースコア(_)から開始される変数名や関数名をチェックします。
これらの名前を許容する場合には、オプション「nomen」を指定します。

悪い例と検査結果

検査対象コード
function _hoge() {
  "use strict";
  var _num = 0;
  _num += 1;
}
検査結果
jslint:test.js:1:10:Unexpected dangling '_' in '_hoge'.
jslint:test.js:3:7:Unexpected dangling '_' in '_num'.
jslint:test.js:4:3:Unexpected dangling '_' in '_num'.

Tolerate HTML event handlers

HTML上でのイベントハンドラをチェックします。
許容する場合は、オプション「on」を指定します。

悪い例と検査結果

検査対象コード
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title></title>
</head>
<body>
<div onclick=""></div>
</body>
</html>
検査結果
jslint:test.html:8:13:Avoid HTML event handlers.

Stop on first error

最初のエラーでチェックを止める場合に、オプション「passfail」を指定します。

このオプションを指定した場合、最初のエラー時に以下のようなメッセージが出力されます。

jslint:test.js:4:7:Combine this with the previous 'var' statement.
jslint:test.js:4:7:Stopping.  (30% scanned).

Tolerate ++ and --

インクリメント、デクリメント演算子の使用をチェックします。
許容する場合には、オプション「plusplus」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var num = 0;

  num++;
  ++num;
  num--;
  --num;
}
検査結果
jslint:test.js:5:6:Unexpected '++'.
jslint:test.js:6:3:Unexpected '++'.
jslint:test.js:7:6:Unexpected '--'.
jslint:test.js:8:3:Unexpected '--'.

Predefined ( , separated)

宣言されていないグローバル変数の使用をチェックします。
これらを許容する場合には、オプション「predef」に宣言済み変数名をカンマ区切りで指定します。
例えば、$とjQueryを宣言済みとする場合は、「$,jQuery」と指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";

  n = n + 1;
}
検査結果
jslint:test.js:6:3:'n' was used before it was defined.

Tolerate . and [^...]. in /RegExp/

正規表現(//)ないでの[^...]の使用をチェックします。
[^...]を許容する場合は、オプション「regexp」を指定します。

悪い例と検査結果

検査対象コード
function hoge(p) {
  "use strict";
  var a;
  a.match(/[^0-9]+/);
}
検査結果
jslint:test.js:4:13:Insecure '^'.

Tolerate missing 'use strict' pragma

use strictの使用漏れをチェックします。
use strictを使用しない場合は、オプション「sloppy」を指定します。

悪い例と検査結果

検査対象コード
function hoge(p) {
  var a;
}
検査結果
jslint:test.js:2:3:Missing 'use strict' statement.

Tolerate inefficient subscripting

プロパティのアクセス時にドッドではなく、を使用しているものをチェックします。
でのアクセスを許容する場合は、オプション「sub」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var obj,
    a;
  obj.prop = function () {
    return 'fuga';
  };

  a = obj['prop'];  // NG
  a = obj.prop;     // OK
}
検査結果
jslint:test.js:9:11:['prop'] is better written in dot notation.

Tolerate misordered definitions

定義されていないグローバル変数の使用?動作確認できず・・・

Tolerate unused parameters

未使用パラメータのチェック?動作確認できず・・・

Tolerate many var statements per function

変数宣言が関数の先頭で纏めて(単一のvarステートメントで)行われているかをチェックします。
変数宣言を任意の箇所で行うことを許容する場合には、オプション「vars」を指定します。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  var i;
  var arr = [1, 2, 3];
  for (i = 0; i < arr.length; i += 1) {
    var fuga;
  }
}
検査結果
jslint:test.js:4:7:Combine this with the previous 'var' statement.
jslint:test.js:6:9:Combine this with the previous 'var' statement.

Tolerate messy white space

スペースのチェック・・・
例えば

  • 関数名と開始括弧の間にはスペースは不要
  • 二項演算子の前後にはスペースが必要

などなどをチェックする。かなり厳密にチェックされる?

チェックをやめたい場合には、オプション「white」を指定します。

悪い例と検査結果

検査対象コード
function hoge (){
  "use strict";
  var num=0;
  num+=1;
}
検査結果
jslint:test.js:1:15:Unexpected space between 'hoge' and '('.
jslint:test.js:1:17:Expected exactly one space between ')' and '{'.
jslint:test.js:1:17:Missing space between ')' and '{'.
jslint:test.js:3:10:Missing space between 'num' and '='.
jslint:test.js:3:11:Missing space between '=' and '(number)'.
jslint:test.js:4:6:Missing space between 'num' and '+='.
jslint:test.js:4:8:Missing space between '+=' and '1'.

Assume Windows

Windows関連のライブラリ?の使用をチェック。
許容する場合は、オプション「windows」を指定してあげます。

悪い例と検査結果

検査対象コード
function hoge() {
  "use strict";
  Debug.clear();
  CScript.create();
}
検査結果
jslint:test.js:3:3:'Debug' was used before it was defined.
jslint:test.js:4:3:'CScript' was used before it was defined.