はじめに
今回はUnityでIncremental Source GeneratorのAdditionalTextsProviderを利用する方法を紹介したいと思います。
その前に
どこかのバージョンから?かSource GeneratorでSystem.IOを利用できなくなったみたいです。
context.RegisterSourceOutput(sampleProvider, (context, syntax) => { // 「アナライザーに対して禁止された API を使用しない」というエラーが出る var txt = System.IO.File.ReadAllText("path-to-txt"); });
RS1035: シンボル 'File' はアナライザーによって使用禁止です: Do not do file IO in analyzers
おそらく入力に対して一意に出力が決まるべきという思想があるのだと思います(多分)。特にIncrementalを実現するためには、それが重要なのかと。
AdditionalFilesを利用してファイルを読み込む
そこでAdditionalFilesを利用することで、指定したパスにあるファイルを読み取ることができます。やり方としては.csprojに以下を追加してあげます。
<ItemGroup>
<AdditionalFiles Include="読み取りたいファイルへのパス" />
</ItemGroup>
これを受け取るにはAdditionalTextsProviderを利用してあげます。
[Generator(LanguageNames.CSharp)] public class SampleSourceGenerator : IIncrementalGenerator { public void Initialize(IncrementalGeneratorInitializationContext context) { var provider = context.AdditionalTextsProvider; context.RegisterSourceOutput(provider, static (context, additionalText) => { var source = $$$""" // FilePath : {{{additionalText.Path}}} """; context.AddSource("Sample.Generated.cs", source); }); } }
Unityでの場合
Unityでは.csprojは自動生成されるため、基本的にユーザーは追記することができません。そこでcsc.rspを利用することで実現できます。ファイルを置く場所はAdditionalFilesの定義を加えたい.asmdefと同階層です。(.asmdefを利用していない場合はAssets/csc.rps)
↓ csc.rsp
/additionalfile:Assets/Scripts/Definition/Sample.cs
ちょっとした裏技(?)
AdditionalFilesとして.csを読み取り、SourceGenerator上で構文解析するという裏技もあったりします。これを利用すれば、アセンブリを超えて色々できちゃいます。
var provider = context.AdditionalTextsProvider .Where(x => x.Path.EndsWith("Hoge.cs")); context.RegisterSourceOutput(provider, static (context, additionalText) => { // additionalTextから構文解析 SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(additionalText.GetText()); // 色々中身を解析していく... // やろうと思えばコンパイルもできるはず });