JavaScriptの静的解析によりコード補完やクロスリファレンスを実現するatom-ternjsの紹介

去年は初日に
http://qiita.com/s-shin/items/203e0f8c0aa00cfacfc5
こんな啓蒙記事を書きました。

あれからメジャーバージョンアップもあり、デフォルトテーマが変わったり、一部有名Packageがビルトインになったり、少しコミットしたに過ぎないにもかかわらずContributor Patchをもらったりしました。

![Contributor Patch](https://qiita-image-store.s3.amazonaws.com/0/7118/44433574-e4a4-3a97-5afe-f05cc75e40f6.png)

ということで、今年も2015年版として誘いを書くことを考えましたが、全体的に見ればさほど変わってない気もしたので、今回は定番ネタではありますがPackage紹介をしたいと思います。

# JavaScriptの静的解析によりコード補完やクロスリファレンスを実現する[atom-ternjs](https://atom.io/packages/atom-ternjs)の紹介

長いタイトルになりましたが、今回紹介するのはatom-ternjsです。

![atom-ternjs](https://qiita-image-store.s3.amazonaws.com/0/7118/0bb29fef-f29b-c5cf-580c-dc26b05b879d.png)

ググっても日本語の記事は中々見つからず、国内ではそれほど話題になっていないようですが、[Tern](http://ternjs.net/)というJavaScript静的解析エンジンプロジェクトがあります[^1]。開発はかなりアクティブです。

Tern自体は、様々なエディタに対応するため独立したサーバーとして動作する仕組みになっており、atom-ternjsはAtom用のフロント実装という位置づけになります。

今回は、なるべくTern自体への深入りは避けるようにし[^2]、特徴や導入などを簡単に紹介しようかと思います。

## Ternの特徴

[詳しくはDocumentを参照](http://ternjs.net/doc/manual.html)ということにしたいと思いますが、個人的に特に嬉しいものとしては以下の2つです。

* 型解析
    * JSDocサポート
    * 一箇所で型が明示されていれば、派生的部分は推論してくれます。
* nodeやES6に対応
    * requireやimportなどもOK

全体的に、多少の不整合があっても、よしなに取り扱ってくれる印象です。

## 実際に使ってみる

導入手順は以下の通りです。

1. atom-ternjsをインストール
2. `.tern-project`の作成
3. サーバー起動
4. Happy Coding!

### 1. atom-ternjsをインストール

普段通りPackageを入れればOKです。
Tern自体も含まれているので、別途準備したりする必要はありません。
楽でよいですね。

### 2. `.tern-project`の作成

JSONで書きます。
簡易的ではありますが`Tern: OpenConfig`で設定も可能です。

とりあえずこんな感じにしてみます。

```json:.tern-project
{
  "libs": [
    "browser"
  ],
  "plugins": {
    "doc_comment": {},
    "complete_strings": {},
    "node": {},
    "es_modules": {}
  }
}
```

libsには[JSON type definitions](http://ternjs.net/doc/manual.html#typedef)[^3]を指定することができ、デフォルトでは https://github.com/ternjs/tern/tree/master/defs にあるものが利用できます。
また、試してないのでどの程度使えるものかは分かりませんが、[bin/from_ts](http://ternjs.net/doc/manual.html#utils)でTypeScriptの`.d.ts`から変換もできるようです。

pluginsには[ビルトインではこの辺りにあるもの](http://ternjs.net/doc/manual.html#plugins)を利用できます。
例えばJSDocやCommonJSスタイルのrequireのサポートなどはpluginとして提供されていることが分かります。

他にも色々設定項目がありますが、ここでは省略します。

### 3. サーバー起動

この辺りはatom-ternjsのドキュメントに従うことになりますが、諸々設定をしたらサーバーのリスタートが必要なようです。

メニューかCommand Palette (`Tern: Restart`) から行えばOKです。

### 4. Happy Coding!

![happy_coding.gif](https://qiita-image-store.s3.amazonaws.com/0/7118/def1476b-2eb8-6bef-b972-f12f8c8e0d53.gif)

## 現時点での問題点

致命的なものとして、長く使っていると次第に補完動作が許容できないレベルまで遅くなることがあります。
`.tern-project`の設定[^4]で良くなる可能性はありますが、もしTernサーバーではなくatom-ternjsの問題だと少し悩ましいかもしれません。

それらしいissueも上がっているようなので、もう少し様子を見たいと思います。

# おまけ

C#の場合は、OmniSharpというTern的な位置づけのOSSがあり、[Package](https://atom.io/packages/omnisharp-atom)も既にあります。

TypeScriptの場合は、[atom-typescript](https://atom.io/packages/atom-typescript)という補完が優秀な鉄板Packageがありますが、こちらも解析用のworkerプロセスを別に立てるアプローチをとっているようです。

それから、最近[Visual Studio Code](https://code.visualstudio.com/)のオープンソース化が話題になりましたが、どうも[一部の言語でIntelliSense対応がされている](https://code.visualstudio.com/Docs/languages/overview)らしいです。この辺り、vscodeから分離し、サーバーとしてOSS化されると夢が広がりんぐですが、今後に期待といった所でしょうか。


[^1]: ternのサブプロジェクトに[acorn](https://github.com/ternjs/acorn)というJSパーサーがありますが、こちら単独でかなり有名です。JSパーサーのポジションは、以前は[esprima](http://esprima.org/)が握ってましたが、最近では[babel](https://github.com/babel/babel/tree/master/packages/babylon)や[JSX](https://github.com/facebook/esprima/issues/111)や[eslint](https://github.com/eslint/espree)もacornベースになるなど、ESTree生成のデファクトになりつつあります。
[^2]: そもそも自分自身まだnewbieなので細かい話はまだ出来ないこともあり。
[^3]: `.d.ts`のようなinterface宣言ファイルです。
[^4]: `dependencyBudget`を減らすなど