💭

夢のソースジェネレーター

に公開1

InjectableGenerator はソースジェネレーターに処理を注入できるソースジェネレーターです。Antigravity 製 で Unity でも動きます。

つかいかた

Generate メソッドの定義が長いですが、[assembly: InjectableGenerator(typeof(...))] を入力するとコード修正が使えるので暗記する必要はないです。

using InjectableGenerator;
using System.Linq;
using Test;

[assembly: InjectableGenerator(typeof(CSharpScript))]

namespace Test
{
    public class CSharpScript
    {
        // アセンブリー内のすべての型に対して実行される
        public static bool Generate(
            System.Type type,
            bool isPartial,
            bool isRecord,
            out string? info,
            out string? warning,
            out string? error,
            out string? source)
        {
            info = warning = error = source = null;

            // ※ typeof でエラーが出る場合は .Name でチェックする
            if (type == typeof(<対象となる型>))
            {
                source = "// 設定した文字列がそのままジェネレーターの出力になる\n"
                       + "// " + string.Join(", ", type.GetFields().Select(x => x.Name));

                // ソース生成する場合は true
                return true;
            }

            // 排他的ではないので警告とエラーを同時に出すことも可
            error = "NOT ALLOWED";
            return false;
        }
    }
}

動作している様子

error にメッセージを指定するとエラーを起こせます。Unity のコンソールにもちゃんとエラーが出ます。(コンパイルが通りません)

使いどころ

構造上「同じアセンブリー内で生成したソースにアクセスできない」という微妙な問題があります。

他にも

  • コードを全てアナライザー上でコンパイル(対象と複製2つのアセンブリーがある状態)
  • 「アナライザー上でコンパイルしたアセンブリー内の型」に対して Generate を実行
    • FullyQualifiedName は使えるが「生成したコード内」では不正な状態
  • 結果はアナライザーの対象アセンブリー内に生成
  • ※ AI 曰く「.NET Standard 2.0 だと System.Runtime.Loader が Unload をサポートしていない」
    • アナライザーが走る度に新たなアセンブリーがメモリーにロードされる状態(多分

という気になる点もあります。

なので、ソース生成も出来ますが現実的な使いどころとしては、インターフェイスで補足できないコード規約のチェックとかでしょうか。(IDisposable をメンバーに抱えているのに IDisposable を実装していない等)

IDE の動作が重い場合はアセンブリー分けや CI 上でのみパッケージを参照する等の措置も必要

Antigravity 製

Google Antigravity 良い感じですね! 雑な指示出しでほぼ全部作ってくれました。作業のペースをこっちが握れるのもデカいです。

他の AI ではわざわざ指示して出力させるようなレポートも勝手に出してくれます。なんなら [MODIFY] みたいな編集種別の表示も思考盗聴か? ってぐらい期待通りのフォーマットです。

Tab 補完が鬱陶しい位でエディターの出来も文句ないです。

おわりに

C# にマクロが欲しいと思っている方も多いと思いますが、C# の場合はマクロではなく Roslyn というソースジェネレーターを使う必要があります。

Roslyn はマクロと違って高性能すぎるというか、構文木とかどうでも良いからサクッとコード生成させろって感じなので AI に代わりを作らせてみたんですが、、、うーーーんって感じですね。筋は悪くないと思うんですが仕組み的に厳しい感。

https://www.nuget.org/packages/InjectableGenerator

以上です。お疲れ様でした。

Discussion

radian-jpradian-jp

ソースジェネレータに処理を注入は面白い発想ですね。
なんか色々応用出来そうな気がします。