WartRemoverをScala 3のTASTy inspector経由で動かす

1週間前のScalaMatsuriで発表 し、色々と話をしたわけですが、それから数日経ってScala 3対応版のwartremoverリリースして、さらに色々と試行錯誤していたら、以下のようなことに気が付き、

やってみたら出来ました、という話。ScalaMatsuriの発表の最後の方で言及していたTASTyの話ですね。その時はこれに全く気がついていなかった。

大体のことをtweetしてしまってるのと、逆に1から全てを説明すると長くなって辛いので、要点だけまとめると

  • TASTyとはScala 3から導入された、ほぼ全てのメタ情報が入ったファイル。デフォルトではJVM用のclassファイルと共に、jarの中に埋め込まれる。
  • TASTy inspectorとは、そのTASTyファイルを、任意のタイミングでparseして scala.quoted.QuotesAPIを使って、任意の解析が出来るもの(よってlinterなどにうってつけである?)
    • 任意のタイミングとは、compileの時に、時間の増加や変なエラー発生含めた、一切の悪影響を与えずに済むメリットがある。
    • 例えばcompiler pluginとしてはwartremoverを使わずに、普通にcompileが終わった後に、testとlinter実行を別々に並列実行、などが可能になる
  • https://github.com/lampepfl/dotty/blob/3.1.1/library/src/scala/quoted/Quotes.scala
  • TASTy inspectorはscala3-compilerに依存しており、Scala 3公式リポジトリで、Scala 3本体と同じサイクルで、開発、リリースされている
  • https://github.com/lampepfl/dotty/tree/3.1.1/tasty-inspector/src/scala/tasty/inspector
  • TASTy inspectorは、compilerに依存はしているが、普通はcompile時に同時に動作させるものではないので、いわゆるcompiler pluginとは微妙に別のものである
  • https://repo1.maven.org/maven2/org/scala-lang/scala3-tasty-inspector_3
  • https://docs.scala-lang.org/scala3/reference/metaprogramming/tasty-inspect.html
  • このblog書いてる時点の安定版である3.1.1や3.1.2-RC3では、わりと致命的なbugがありそうで、明らかに動かなかったり変な動きをするため、今回はNIGHTLYを使っている
  • tweetした通りだが、基本的にwartremoverが scala.quoted.Quotes を使うように設計したのと、TASTy inspectorがQuotesとそのTreeを渡してくる、という設計になっているので、そのまま動く(ただし現状だとNIGHTLYのみ)
  • これもtweetしたが、せっかくだからcoursierで色々と任意のjarを取れるようにして、色々なライブラリを試していた(TASTy inspectorにjar丸ごと渡して解析できるメソッドが用意されている)
  • (依存増えるので)おそらくsbt的には別のsub projectとしてwartremover本体に入れたいが、どういう形がいいのか?を模索中なため、とりあえず最低限のわかりやすいサンプル切り出したので、それをblogに書いている、という経緯
  • ここ数日wartremover関連で色々やったおかげで、関連するようなしないようなbugっぽいものを色々見つけて報告しました

gist.github.com