メインコンテンツまでスキップ

Immutablesの処理構造メモ

Sato Taichi

Immutables は Annotation Processor として動作するコードの自動生成系テクノロジです。Immutables はヘビーに Annotation Processor を使って実装されているので、コードの見通しが凄く悪いので理解の断片をメモ書きしておきます。

これは主に未来の自分用メモです。

ユーザ用アノテーションが定義されているプロジェクト#

処理は無い。普通に使うだけなら、ここだけ見てれば使える。

  • builder
  • cases
  • gson
  • metainf
    • これは処理を持ってる。META-INF/services/にファイル吐くアレ。
  • mongo
  • ordinal
  • serial

テスト用プロジェクト#

testing はアサーションとかアレが入っている

テストデータ#

  • generator-fixture
  • value-fixture

コード生成用テンプレートエンジン#

Immutables では、コード生成用のテンプレートエンジンをparboiledベースで実装している。

そのつなぎ込みにかなりの量のコードを書いている。

generator#

テンプレートエンジンのランタイム部分。 javac と ECJ のコンパイラ動作差分を吸収するためのコードもここにある。

generator-processor#

Immutables 自体を実装するために使っている Annotation Processor 部分。 Immutables の独自テンプレートエンジンはテンプレートファイルを Annotation Processor の API 経由で Java のソースコードに落としてから動かすという、JSP に似たような動作をする。

このプロジェクトでは、テンプレートエンジンとそれに食わせるモデルオブジェクトのつなぎ込み処理が為される。

その為、任意のモデルオブジェクトをテンプレートエンジンに都合よく解釈するためのコードがかなり含まれており、Annotation Processor 実装者が参考になるコードが多い。

Accessorsは、フィールド経由のアクセスと Getter、Setter 経由のメンバアクセスをモデル化するコードである。

Importsは、Annotation Processor におけるインポート宣言が超テキトーになる問題と真っ向から戦っており、その必要性の是非はあるものの参考になる。

コードフォーマッタ系のコード群#

  • Spacing
  • Balancing
  • Inliner

この辺はテンプレートエンジンべったりな生成物の最適化処理なので余り参考にはならない。

Treesはテンプレートエンジンの AST が定義されている。TypeResolver 辺りはこの AST を前提に動作する。

mirror#

アノーテーションから読み取った情報を格納するミラーオブジェクトを生成する Annotation Processor。

generator-processor プロジェクトの動作を理解するのには丁度いい大きさのコードベースになっている。ビルド環境を整えて生成されるコードを眺めることで、Immutables がどのような設計になっているのか何となく理解の端緒を掴めるだろう。

というか、恐ろしく少ないコードで Annotation Processor を実装できてしまっている。

value-processor#

Immutables の本体部分。javax.annotation.processing.AbstractProcessor の子孫であるところのProcessorが余りにスッキリしたコードなので驚く。

ValueType と ValueAttribute が完全にゴッドオブジェクトになってしまっている。 しかしもって Proto と ValueType の責任分界点がどこにあるのかサッパリ分からない感じではある。

謎アーティファクトについて#

各所のプロジェクトが依存しているorg.immutables:value-standaloneというアーティファクトがあって、中身を何となくみると Maven Shade Plugin が動いた後の Immutables って感じなんですけども、現状のものとは内容物に大きな差があるのですよね。

恐らく 2.0 系開発にあたってプロジェクト体系が大きく見直された結果、1.1 系と大きな隔絶が発生したのだけども、Immutables は Immutables を使って実装するというセルフホスティング的な思想で実現されているため、現状 1.1 系への依存性が残ってしまっている…みたいな話ではないかなぁ…とは思います。

しかし、Maven Central Repository にアップロードされている 1.1 系は-sources.jar が適切な状態で無いために正しいソースコードがキチンとデプロイされていません。 ディスアセンブルしてまでつぶさに中を確認したいって気持ちも薄いので、とりあえずほっとくかなぁ…という感じです、ええ。