[Closure Compiler]型定義チェックでコードの品質を向上する
前のエントリで紹介した、Google製JavaScriptコード圧縮・最適化ツールClosure Compilerだが、コメントで型定義を行うことで強力な警告機能を利用できる。
コメントの構文はJsDocの記法に従う。基本的な書き方は JsDoc Toolkitを使う! - ドックコメントの書き方 を参照。
型定義の記法は、Closure Compilerを使う! - アノテーションによる型定義 を参照。
タグについては、とりあえず以下を押さえておけばいいと思う。
・クラスには @constructor をつける。
・プロパティの型は @type で記述。
・引数の型は @param、戻り値の型は @return で記述。
・複雑な型の別名は @typedef で宣言。
大事なのは型表現なので、ここはひと通り目を通すことをお勧めする。
指定できる型は、Google JavaScript Style Guide - JavaScript Types の Types in JavaScript に一覧がある。
それでは、Closure Compilerの利用方法を説明する。
<テスト対称コード sample.js>
型定義チェックを行うには、--warning_level VERBOSE をつける。
windowsのコマンドプロンプトで実行する場合、実行コマンドは以下のようになる。
コマンド実行結果は以下のとおり。
Closure Compilerのすごいところは、単に型チェックをするだけではなく、コードの解析も行っていること。
この警告を受けて次のようにコードを修正すると、警告が出なくなる。
このように、型表現を駆使した型定義を書いてClosure Compilerでチェックすることで、想定外のデータが入力される可能性を減らすことができる。
厳密に入力チェックをしていないprivateメソッドなどではかなり有効。
なお、Closure Compiler用の型定義でjsdoc_toolkit-2.4.0を実行したところ、JsDoc Toolkitが認識できないものがあった。
・@typedef を認識しない
・@type の型を{ }で囲った場合、{ }内を出力しない
・配列の型を Array.<...> と書いた場合、< >内を出力しない
JsDocを出力する場合は要注意。
コメントの構文はJsDocの記法に従う。基本的な書き方は JsDoc Toolkitを使う! - ドックコメントの書き方 を参照。
型定義の記法は、Closure Compilerを使う! - アノテーションによる型定義 を参照。
タグについては、とりあえず以下を押さえておけばいいと思う。
・クラスには @constructor をつける。
・プロパティの型は @type で記述。
・引数の型は @param、戻り値の型は @return で記述。
・複雑な型の別名は @typedef で宣言。
大事なのは型表現なので、ここはひと通り目を通すことをお勧めする。
指定できる型は、Google JavaScript Style Guide - JavaScript Types の Types in JavaScript に一覧がある。
それでは、Closure Compilerの利用方法を説明する。
<テスト対称コード sample.js>
/**
* @namespace
*/
var ccsample = {};
/** @typedef {{x: number, y: number, z: number}} */
ccsample.Vector;
/**
* 図形クラス。四角形または三角形を管理。
* @param {ccsample.Vector} i0 頂点
* @param {ccsample.Vector} i1 頂点
* @param {ccsample.Vector} i2 頂点
* @param {?ccsample.Vector} i3 頂点
* @constructor
*/
ccsample.Quad = function(i0, i1, i2, i3) {
/** @type {ccsample.Vector} */
this.i0 = ccsample.copyVec(i0);
/** @type {ccsample.Vector} */
this.i1 = ccsample.copyVec(i1);
/** @type {ccsample.Vector} */
this.i2 = ccsample.copyVec(i2);
/** @type {?ccsample.Vector} */
this.i3 = ccsample.copyVec(i3);
};
/**
* Vectorをコピー
* @param {ccsample.Vector} vec コピー元Vector
* @return {ccsample.Vector} コピー結果
*/
ccsample.copyVec = function(vec) {
return {x: vec.x, y: vec.y, z: vec.z};
};
* @namespace
*/
var ccsample = {};
/** @typedef {{x: number, y: number, z: number}} */
ccsample.Vector;
/**
* 図形クラス。四角形または三角形を管理。
* @param {ccsample.Vector} i0 頂点
* @param {ccsample.Vector} i1 頂点
* @param {ccsample.Vector} i2 頂点
* @param {?ccsample.Vector} i3 頂点
* @constructor
*/
ccsample.Quad = function(i0, i1, i2, i3) {
/** @type {ccsample.Vector} */
this.i0 = ccsample.copyVec(i0);
/** @type {ccsample.Vector} */
this.i1 = ccsample.copyVec(i1);
/** @type {ccsample.Vector} */
this.i2 = ccsample.copyVec(i2);
/** @type {?ccsample.Vector} */
this.i3 = ccsample.copyVec(i3);
};
/**
* Vectorをコピー
* @param {ccsample.Vector} vec コピー元Vector
* @return {ccsample.Vector} コピー結果
*/
ccsample.copyVec = function(vec) {
return {x: vec.x, y: vec.y, z: vec.z};
};
型定義チェックを行うには、--warning_level VERBOSE をつける。
windowsのコマンドプロンプトで実行する場合、実行コマンドは以下のようになる。
java -jar compiler.jar --warning_level VERBOSE --js sample.js --js_output_file sampleout.js > gccout.txt 2>&1
標準出力をgccout.txtにリダイレクトしている。エラーや警告は標準エラー出力に出力されるため、2>&1で標準エラー出力もリダイレクトしている。コマンド実行結果は以下のとおり。
sample.js:25: WARNING - actual parameter 1 of ccsample.copyVec does not match formal parameter
found : (null|{x: number, y: number, z: number})
required: {x: number, y: number, z: number}
this.i3 = ccsample.copyVec(i3);
ccsample.copyVecはnullを許容しないのに、上記の箇所でnullが入力される可能性があると警告してくれる。found : (null|{x: number, y: number, z: number})
required: {x: number, y: number, z: number}
this.i3 = ccsample.copyVec(i3);
Closure Compilerのすごいところは、単に型チェックをするだけではなく、コードの解析も行っていること。
この警告を受けて次のようにコードを修正すると、警告が出なくなる。
/** @type {?ccsample.Vector} */
this.i3 = null;
if (i3 !== null) {
this.i3 = ccsample.copyVec(i3);
}
条件演算子もちゃんと解析してくれるので、以下のように書いてもいい。this.i3 = null;
if (i3 !== null) {
this.i3 = ccsample.copyVec(i3);
}
this.i3 = (i3 === null) ? null : ccsample.copyVec(i3);
このように、型表現を駆使した型定義を書いてClosure Compilerでチェックすることで、想定外のデータが入力される可能性を減らすことができる。
厳密に入力チェックをしていないprivateメソッドなどではかなり有効。
なお、Closure Compiler用の型定義でjsdoc_toolkit-2.4.0を実行したところ、JsDoc Toolkitが認識できないものがあった。
・@typedef を認識しない
・@type の型を{ }で囲った場合、{ }内を出力しない
・配列の型を Array.<...> と書いた場合、< >内を出力しない
JsDocを出力する場合は要注意。
スポンサーサイト