今さらながら知ったWebStormとJSDocの深〜い関係

正宗です。ものすごく今さらな事を知ったのでおおはしゃぎで書き留めておきます。いかに今までまともにJSDocを書いていなかったか。

私が主に JavaScriptを書くときに使っているWebStormでJSDocをきちんと書くようにすると、JavaScriptの型をなかなか強力にサポートしてくれるようになりました。コードの補完機能なんかもかなり精度が上がってくるので、結果的にコーディングも速くなるのではないでしょうか。
私は特に普段はActionScript3を書く機会が多く、ご存じのとおりActionScript3は型を明示できる言語なのでFlashBuilderやFlashDevelop、FlashCS5などのIDEに備わっている補完機能に頼り切ってコーディングしていました。そのスタイルのままJavaScriptのほうの開発を行うと、今まではJavaScriptで厳密に型を明示できないことで自分のスペックの低さによってコーディングが遅くスペルミスも多いという弱点となってしまっていたのです。ですがWebStormがJSDocをここまでサポートしてくれていると、普段からコードにドキュメントを残すことで型の整合性をチェックできつつ補完の精度も上がっていくという、まさに一石何鳥も得たりという思いです。まさにWebStormさまさま!これには野鳥愛好家も黙っていられないんではないでしょうか。

あと毎度の事ながら前置きですがこの記事ではJSDocの書き方は扱っていません。あくまでJSDocに型情報を書いていったらどこまでWebStormが補完してくれるか、だけ実験しています。 

基本形何発か

まずはこの状態。

;
var name = "utsunomiya";

この状態で1行目にカーソルを入れて、/**(半角スラッシュひとつと半角アスタリスク(肛門みたいなの)ふたつ)を入れてEnter

/**
 *
 * @type {String}
 */
var name = "utsunomiya";

あとはここまで補完してくれます。うん、便利。

プリミティブな型やクラスは当然びしびし補完してくれます。
以下、同じように半角スラッシュと肛門ふたつで自動的に補完してくれる型を紹介します。 

/**
 *
 * @type {Number}
 */
var age = 37;
/**
 *
 * @type {Date}
 */
var date = new Date();

関数なんかがかなり強力です。
実際にこんな変な関数書くことはないんですが、JSDocの実験と言うことでご勘弁ください。

function createNames(){
    return [
        "tanaka",
        "yamada",
        "suzuki"
    ];
}

function addName(name){
    var a = createNames();
    a.push(name);
    return a;
}

ここまで書くとしめたものです。

/**
 *
 * @return {Array}
 */
function createNames(){
    return [
        "tanaka",
        "yamada",
        "suzuki"
    ];
}
/**
 *
 * @param name
 * @return {Array}
 */
function addName(name){
    var a = createNames();
    a.push(name);
    return a;
}

一気にここまで補完してくれました。
特にaddNameのローカル変数aに注目して欲しいんですが、ちゃんとcreateNamesの戻り値がArrayだっていうことを参照していらっしゃる。
IDEがここまでコードの意味を理解しているようになるといろいろと安心ですね。 

もちろんユーザー定義クラスなんかも言わずもがな。

/**
 *
 * @constructor
 */
function Main(){};
/**
 *
 * @type {Main}
 */
var main = new Main();

はいはい自動自動。

ActionScript3でいうところのVectorなんかはどう?

ActionScript3でよく使うVector.<String>こういった書き方はどうでしょうか?
結論から言いますと、@type {Vector.<String>}もいけました。AS3er歓喜です。

/**
 *
 * @return {Vector.<String>}
 */
function createNames(){
    return [
        "tanaka",
        "yamada",
        "suzuki"
    ];
}
/**
 *
 * @type {Vector.<String>}
 */
var people = createNames();
/**
 *
 * @type {String}
 */
var person = createNames()[0];

ただ、僕が何とかのひとつ覚えみたいにJavaScript書くときバイブルにしているGoogleのコーディング規約によりますとArray.<String>やObject.<String>を推奨していますので、それに従って書くと問題が起こります。

/**
 *
 * @return {Array.<String>}
 */
function createNames(){
    return [
        "tanaka",
        "yamada",
        "suzuki"
    ];
}
/**
 *
 * @type {Array.<String>}
 */
var people = createNames();
/**
 *
 * @type {*}
 */
var person = createNames()[0];

Array.<String>で書くとArrayの中身がStringだということがWebStorm様がご理解いただけない…TT
もしかしたら設定などでレギュレーション出来るのかも知れませんが、情報ありましたら教えて頂くと嬉しいです。それか今後のバージョンアップに期待というところでしょうか。 

もうちょっと複雑なことはできるかな?

このへんになってくるとまだ補完が危うい感じ? 

/**
 *
 * @return {Function}
 */
function test(){
    return function(x, y){
        return x * y;
    }
}
/**
 *
 * @type {*}
 */
var t = test();
console.log(t(2, 5));

test()を実行したときの戻り値が追いかけられてなさそうではあります。
最初のtest()の戻り値がFunctionオブジェクトなので、これだとコンストラクターなのか関数なのかがわからない、ということでしょうか? 

大文字Fのほうでなく、小文字で書いてfunction文を返すことを明記して実験。

/**
 *
 * @return {function():number}
 */
function test(){
    return function(x, y){
        return x * y;
    }
}
/**
 *
 * @type {function():number}
 */
var t = test();
//ここで間違う
var n = t(2, 5);

う〜ん、惜しいなあ。実に惜しい。

/**
 *
 * @return {function}
 */
function test(){
    return function(x, y){
        return x * y;
    }
}
/**
 *
 * @type {*}
 */
var t = test();
/**
 *
 * @type {*}
 */
var n = t(2, 5);

今はこれが精一杯><

IDEの機能に引っ張られてコーディング規約が甘くなるのは本末転倒ですが、あまりIDEの機能に頼りすぎてるとIDEの能力を超えた書き方がバグを混ぜてしまう危険性も出てくるので(しかもその場合、コーダーが気付かないうちに自動的に混ぜてしまう場合が多いのでさらに厄介)そこらへんの線引きは難しいところと言うか、僕みたいなツール頼りすぎなんちゃってプログラマーのつらいところです。

まとめますと、ちょっと癖はありますがかなりコードを深く理解して補完してくれるようになるみたいで、使えそうです。特に普段はActionScript3で慣れたクラス開発型をJavaScriptでも行っているので、ユーザー定義クラスとプリミティブ型オブジェクトをしっかりトラッキングしてくれるところが気に入りました。
それにJSDocでコード補完をより精度を高めていくやり方は、規約とドキュメントのクオリティも高めてくれるので積極的に使っていきたいです。

コメントを残す

メールアドレスが公開されることはありません。