Kotlin Fest 2024 で Kotlin Compiler Plugin の話をしてきたよレポート

こんにちは、こんばんは、kitakkunです。

Kotlin Fest 2024にスピーカーとして参加してきましたので、その感想と補足情報をまとめたいと思います。

自分のセッションで手一杯で他のセッションは全然見れていなくて、自分語り成分だけになります。すみません！！！（アーカイブほしい！！）

[2024/08/30 追記]
アーカイブ動画が公開されたようです。興味のある方はぜひ見てみてください！

https://youtu.be/KeQyaLF-_9A

# 更新履歴

- 2024/06/25: FIR拡張で生成する宣言をIDEに認識させる方法を確認しましたので、そちらの件に関して追記しました。
- 2024/08/30: アーカイブ動画へのリンクを掲載しました。

# 登壇内容

こちらの40分のセッション枠で登壇させていただきました。Kotlin Compiler Pluginに関する発表です。

https://fortee.jp/kotlin-fest-2024/proposal/59aca818-d5d5-4eb4-a123-abae563a7f28

探すの結構大変かと思うのでこちらにもスライド資料とサンプルコードを共有しておきます！

https://speakerdeck.com/kitakkun/kotlin-fest-2024-motutokotlinwohao-kininaru-k2shi-dai-nokotlin-compiler-pluginkai-fa

https://github.com/kitakkun/greeting-plugin

# 発表を終えて（本当にただの感想）

高校や大学で何度かプレゼンはやっているのですが、**公式な場で発表したのは、今回が初めて**でした。

僕の発表は部屋が満席に近い状態だったらしいのですが、~~画面ばっかり見てたので~~ 意外と緊張せず落ち着いて話すことができました！

（ペースを崩すと話しきれない内容だったので、ただただスピーカーノート読み上げてました！理想を言えばもっと前を見て話せたらよかったとは思います😇）

終わってみて第一の所感としては、**想定よりたくさんの方がK2コンパイラ拡張に関心を持たれていた**ということです。
分野的にはかなりニッチな領域だと思っていましたが、さすが言語のカンファレンスなだけあって、皆さんの熱を感じることができました！

FIRやIRといったコンパイラの内部的なプログラムの表現について解説したあと、拡張の基礎的な内容を説明し実装に入っていったのですが、「**わかりやすかった**」とか、「**自分も作れそうかも！**」といったポジティブなフィードバックをたくさんいただけました。

発表中2回ほど会場が沸いた瞬間がありましたが、greeting-pluginのしょうもない内容で笑ってくれた皆さん、そしてback-in-time-pluginで歓声を上げてくれた皆さん、ありがとうございました！

正直あんなに反応がもらえるとは思っていなくて、**イベントをみんなで作り上げる**というのはこういうことなのかと、たくさん元気をもらいました！

# Ask the Speakerでの話

Ask the Speakerのコーナーでは、@takahiromさんをはじめ、JetBrains社で今回スピーカーとして登壇されていた[Yan](https://x.com/yanewm)さんまで、たくさんの方に来ていただけました！

具体的に何を話していたのかは、ありがたいことにtakahiromさんの方でよくまとめていただけていたので、そちらを見ていただければいいかなと思います！

https://qiita.com/takahirom/items/91b38040481cca555f7a

スライドを見れば載っている情報もありますが、参考に少しだけ補足的な情報を追加させていただきます。

## Q1: FIR解決フェーズはどこで情報を得たの？

Kotlin公式リポジトリに [docs](https://github.com/JetBrains/kotlin/blob/master/docs) というディレクトリがあり、この中に [fir-basics.md](https://github.com/JetBrains/kotlin/blob/master/docs/fir/fir-basics.md) というファイルがあります。そしてドキュメント内部で [FirResolvePhase.kt](https://github.com/JetBrains/kotlin/blob/master/compiler/fir/tree/src/org/jetbrains/kotlin/fir/declarations/FirResolvePhase.kt) というコードへのリンクが貼られているのですが、そちらにFIR解決フェーズの詳細がコメントとして載っています。

過去のセッションでこのフェーズに関して細かく解説した資料は見当たりませんでしたし、コンパイラ拡張を作る上でフェーズのことを理解していないと思わぬところでハマりかねないので、しっかり時間を使って解説させていただきました。

上部の知識だけでコンパイラプラグインを作ろうとすると、苦労が大きく嫌いになってしまうかもしれないので、しっかり土台を作った上で、詰まっても自走ができるような構成に仕上げたつもりです。

## Q2: Time Travel DebuggingのあのUIのツーリングどうしている？

現状[Flipper](https://fbflipper.com/)という拡張可能なモバイルアプリのデバッグツールの上に、デバッガーツールを構築しています。TypeScriptを使って書かれており、Reduxアーキテクチャでデータ管理しています。

https://github.com/kitakkun/flipper-plugin-back-in-time

発表の中で、back-in-time-pluginはKMP化に向けて作業している最中と説明しました。Flipperのデバッガー実装のままiOS対応するとなった場合、iOSのFlipper実装とKotlinモジュールを接続しなければならず、とんでもなくめんどくさそうな雰囲気を感じています。ですので、今現在はKtorを使ってなんとかKMPでいい感じにできないかなあと模索している最中です。

有識者の方ヘルプが欲しいです！ とりあえずAndroidではKtorでWebSocket通信ができていることは確認していますが、iOS全然わからんになっています（テストもこけています）。

また、Flipper Pluginは最低限動く機能が実装されていますが、内部的な処理効率が良くなかったり、機能拡張が難しい状態なので、今後メンテナンスを行う予定はありません。

Compose for Desktopを使ったピュアKotlinなデバッガー実装を頑張っているところです。

https://github.com/kitakkun/back-in-time-plugin/pull/18

## Q3: Compiler Pluginって今IDEに読み込まれるの？

Kotlin Slackの中探した感じまだ対応中で JVM は動く、KMPはこれから？という雰囲気の書き込みがありました。

とはいえ、自分が手元でK2モードでIDE動かした感じでは、認識されている気配がなかったのですよね。

ただ、今日よく調べてみたところ、もしかすると標準でビルトインのコンパイラプラグインで生成された部分しか認識しない設定になっているような気配を感じました。要検証です。

https://youtrack.jetbrains.com/issue/KTIJ-29248

:::note info
2024/06/25追記

IntelliJを起動してRegistryという設定項目を開き、`kotlin.k2.only.bundled.compiler.plugins.enabled` というフラグを無効に切り替える（以下チェックが入っている箇所を外す）ことで、IDE上でFIR拡張で生成した宣言を認識することを確認しました。

現時点では標準でビルトインのコンパイラプラグインしか認識しないようですので、コンパイラプラグインを開発する際はこちらのオプションを無効化した上で進めるとよさそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1971624/313d1528-cc0b-632a-4c3b-fea449484777.png)

以下の例では greet関数 が FIR拡張で生成した宣言にあたりますが、Unresolved Reference というエラー表示もなくなっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1971624/cf08551b-03e0-075b-5740-5b8444876588.png)

:::



また、Yanさんが最初の方のコンパイラプラグインの開発に関わっていたというお話も聞けて、
実際に GitHubでKotlin 1.x系におけるコンパイラ拡張登録を行うコンポーネントである ComponentRegistrar を見に行ってみたところ、確かに Yan さんのお名前を見つけることができ、広いようで狭い世界だなあと驚きました！！！

https://github.com/JetBrains/kotlin/commits/v1.9.24/compiler/plugin-api/src/org/jetbrains/kotlin/compiler/plugin/ComponentRegistrar.kt

## 補足(+α）: FirStatusTransformerExtensionについて

（聞き間違いがあったら申し訳ないのですが）
Javaはデフォルトでクラスが継承可能、Kotlinはデフォルトでは継承不可といった違いがあり、それらの違いをなくし互換性を担保するために、FirStatusTransformerExtensionが作られたという背景があるそうです。

All-openという公式のコンパイラプラグインがあるのですが、そこ専用に作られた拡張ポイントという認識のようでした。

https://kotlinlang.org/docs/all-open-plugin.html

自分でも使い所が難しそうと感じていた拡張ポイントではあったので疑問が解けてスッキリしました。

# 発表資料作成の裏話

今回発表させていただいた内容は直前の2週間で何度も変更を重ね、やっとの思いでギリギリに完成したものとなっています。

特に、2週間前の時点の構成と、1週間前の時点でのスライドの構成は全く異なっています。

本番では Gradle DSL とコンパイラ引数への対応を除外してお話しさせていただきましたが、2週間前ではそれらが除外できるという事実を把握しておらず、コンパイラプラグインを構成する5種類の要素全てを説明する資料構成となっていました。

時間的な制約が大きく、具体的な実装例についても省略した内容となっていましたが、1回目の社内発表会をしたときに、「これでは作れるようになる気がしない」というフィードバックを受け、（僕自身も全く同じことを思ったので）構成を大きく変更しました。

具体的な題材が欲しいという話にもなり、3つほどサンプルを作っては壊し、最終的に greeting-plugin に行き着きました。

ここだけの裏話です・・！(笑)

# 最後に

https://x.com/kitakkun_pb/status/1804488981482188915

大学の卒研発表でも、back-in-time-pluginの説明はしたのですが、技術的な部分に関しては細かく触れることができず、また時間も17分と短いため満足いく発表ができていませんでした。

仕方ないといえば仕方がないのですが、不完全燃焼でしたし、今回このような貴重な場を借りて Kotlin Fest の皆さんと Kotlin Compiler の面白い部分を共有できたことがとても嬉しかったです。

コンパイラをここまで柔軟に拡張できる仕組みが整っていることは、Kotlinの一つの強みだと思います。

https://x.com/tbs__ten/status/1804799246383923201

どうやら僕の作った back-in-time-plugin の中身を覗いてみる会も企画されているようで、コミュニティの熱を感じています！！（お邪魔させてもらう予定です）

本当に最後の最後に・・・

https://x.com/kitakkun_pb/status/1805059198109303228

実はまだまだ話し足りないので sansan さんのイベントで 10分 LT に申し込ませていただきました。もうちょっと細かい部分の話をさせていただくつもりですので、お時間合いましたらぜひ！

長くなりましたが、ここまで読んでいただきありがとうございました！
今後ともKotlinのコミュニティを盛り上げていけたらと思います。

# 過去記事

情報が古いかもしれませんが、Kotlin Compiler関連で、過去記事を共有させていただきます。

https://qiita.com/kitakkun/items/f8702d5975809c2bea05

https://qiita.com/kitakkun/items/726da44f94f20d5d578b

https://qiita.com/kitakkun/items/560468df68d41b6f8bb5