Immutablesの処理構造メモ

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が適切な状態で無いために正しいソースコードがキチンとデプロイされていません。 ディスアセンブルしてまでつぶさに中を確認したいって気持ちも薄いので、とりあえずほっとくかなぁ…という感じです、ええ。