为什么不应该在SourceGenerator中读取文件?

huangapple go评论61阅读模式
英文:

Why shouldn't I read files in a SourceGenerator?

问题

我正在创建一个SourceGenerator,它将读取一个YML文件,该文件定义了流畅API的不同状态,然后生成相关的接口来实现语法。

我刚刚看到一个警告,告诉我要在我的csproj中添加EnforceExtendedAnalyzerRules,我已经这样做了。现在它告诉我不应该在分析器中进行文件IO。

我的主要问题是:

  1. 为什么我不应该这样做?
  2. 我应该如何以其他方式获取项目目录内文件的文件内容,作为源生成器的一部分?
英文:

I'm creating a SourceGenerator that will read in a YML file defining the different states of a fluent API and then generate the relevant interfaces to implement the grammar.

I've just seen a warning telling me to add EnforceExtendedAnalyzerRules to my csproj, which I've done. It's now telling me that I shouldn't do File IO in an analyzer.

My main question is:

  1. Why shouldn't I?
  2. How else am I supposed to get the file contents of a file within the project directory as part of a source generator?

答案1

得分: 5

  1. 为什么不应该这样做?

如果你在运行源代码生成器,你必须明白生成器将会在IDE的每个生成阶段中运行(可能在每次按键或类似事件中运行)。你可以想象一下,如果你的源代码生成器频繁地执行I/O操作,你的IDE体验会变得缓慢

微软通过发布新的增量生成器API来解决了这个问题,该API推迟了在初始化生成器时设置的提供程序的执行,直到对它们进行更改,并在可能的情况下缓存结果。

  1. 我应该如何以其他方式获取项目目录中文件的内容,作为源代码生成器的一部分?

如果你能够在项目中将你的Yaml文件注册为csproj的additional file

<ItemGroup>
    <AdditionalFiles Include="myfile.yml" />
</ItemGroup>

你可以按以下方式获取你的yml文件(如果你正在使用增量生成器):

[Generator(Language.CSharp)]
public class MyGenerator : IIncrementalGenerator
{
    public void Initialize(IIncrementalGeneratorInitializationContext initContext)
    {
        var ymlFiles = initContext.AdditionalTextProviders.Where(static file => file.Path.EndsWith(".yml"));

        var ymlFileContents = ymlFiles.Select((text, cancellationToken) => text.GetText(cancellationToken)!.ToString());

        // 如果你注册了更多的文件作为附加文件,这一步是可选的
        var ymlFileContentsToUse = ymlFileContents.Where(content => content.Contains("keyword"));

        // 添加更多的提供程序

        // 最后,你可以这样做
        // Collect将开始评估你的值提供程序,并应在最后调用
        var provider = ymlFileContentsToUse.Collect();

        initContext.RegisterSourceOutput(provider, (context, source) =>
        {
            // 在这里生成源文件
        });
    }
}
英文:

> 1. Why shouldn't I?

If you're running a source generator, you have to understand that the generator will run for every generation phase in the IDE (which may run every key stroke or similar events). You can imagine if your source generator is running that frequently doing I/O operations, your IDE experience will slow down.

Microsoft have resolved this by releasing the new Incremental Generator API which defers execution of the providers you setup when initializing the generator until there is a change to them, and will cache the results where possible.

> 2. How else am I supposed to get the file contents of a file within the project directory as part of a source generator?

If you're able to register your Yaml file in your project as an additional file in your csproj:

&lt;ItemGroup&gt;
    &lt;AdditionalFiles Include=&quot;myfile.yml&quot; /&gt;
&lt;/ItemGroup&gt;

You can get your yml file in the following way (if you are using an Incremental Generator):

[Generator(Language.CSharp)]
public class MyGenerator : IIncrementalGenerator
{
    public void Initialize(IIncrementalGeneratorInitializationContext initContext)
    {
        var ymlFiles = initContext.AdditionalTextProviders.Where(static file =&gt; file.Path.EndsWith(&quot;.yml&quot;));

        var ymlFileContents = ymlFiles.Select((text, cancellationToken) =&gt; text.GetText(cancellationToken)!.ToString());

        // Optional if you have more registered as an additional file as yml
        var ymlFileContentsToUse = ymlFileContents.Where(content =&gt; content.Contains(&quot;keyword&quot;));

        // Add more providers

        // At the end, you can do something like
        // Collect will start evaluating your value providers, and should be called at the end
        var provider = ymlFileContentsToUse.Collect();

        initContext.RegisterSourceOutput(provider, (context, source) =&gt;
        {
            // Generate source files here
        });
    }
}

huangapple
  • 本文由 发表于 2023年6月12日 09:37:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453208.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定