简体   繁体   English

在源代码生成器中添加非 C# 文件

[英]Add non-C# files in source generators

I'm creating a source generator that creates Typescript utilities based on user C# code, right now the only efficient way to create a file is AddSource() method, which can only create *.cs files.我正在创建一个源代码生成器,它根据用户 C# 代码创建 Typescript 个实用程序,现在创建文件的唯一有效方法是AddSource()方法,它只能创建*.cs文件。

I need to create *.ts files (or *.js ), using File.Write* is also a pain, because the path and referencing project are unknown ( Environment.CurrentDirectory will return the generator path which is not even close to user project) to generator, currently the only way to find the path is:我需要创建*.ts文件(或*.js ),使用File.Write*也很痛苦,因为路径和引用项目是未知的( Environment.CurrentDirectory将返回甚至不接近用户项目的生成器路径) 到生成器,目前找到路径的唯一方法是:

var baseFilePath = context.Compilation.SyntaxTrees.First(x => x.HasCompilationUnitRoot).FilePath;

var myDir = Path.Combine(Path.GetDirectoryName(baseFilePath)!, "tsFiles");

from here .从这里

which as you can see is not really nice and safe and it would be a performance killer since it cannot be used in Initialize method, it has to be in Execute method which will execute forever and you have to either put an if statement to check File.Exists() or it will create that file for ever.如您所见,这不是很好和安全,并且它将成为性能杀手,因为它不能在Initialize方法中使用,它必须在将永远执行的Execute方法中,并且您必须放置一个 if 语句来检查File.Exists()否则它将永远创建该文件。

Considering all these, what is the most efficient way to create non-C# files (both in startup and execution time)考虑到所有这些,创建非 C# 文件的最有效方法是什么(启动和执行时间)

For either a ISourceGenerator or IIncrementalGenerator, you should be able to access the target project's "build_property.projectdir" value from AnalyzerConfigOptions.对于 ISourceGenerator 或 IIncrementalGenerator,您应该能够从 AnalyzerConfigOptions 访问目标项目的“build_property.projectdir”值。

The following is a gist that I use for the same thing in an IIncrementalGenerator.以下是我在 IIncrementalGenerator 中用于同一事物的要点。

IncrementalValueProvider<string?> projectDirProvider = context.AnalyzerConfigOptionsProvider
    .Select(static (provider, _) => { 
        provider.GlobalOptions.TryGetValue("build_property.projectdir", out string? projectDirectory);

        return projectDirectory;
});
   

context.RegisterSourceOutput(
    projectDirProvider, 
    static (context, source) => {
    
    string? projectDirectory = source;

});

This will give you the base/root directory of your target project and from there you should be able to use System.IO for what you need.这将为您提供目标项目的基本/根目录,您应该可以从那里使用 System.IO 来满足您的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM